package com.ruoyi.app.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.enums.UserStatusEnum;
import com.ruoyi.bizsys.mapper.AppUserMapper;
import com.ruoyi.bizsys.mapper.CustomerInfoMapper;
import com.ruoyi.bizsys.mapper.LoanIouDeferredMapper;
import com.ruoyi.bizsys.mapper.ProductInfoMapper;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.bizsys.utils.UserCacheService;
import com.ruoyi.bizsys.vo.BankAccountVo;
import com.ruoyi.business.Vo.RulePremiseVo;
import com.ruoyi.business.common.AsyncService;
import com.ruoyi.business.common.riskRule.LoanRule;
import com.ruoyi.business.common.riskRule.RulePremiseService;
import com.ruoyi.business.common.riskRule.RuleStrategy;
import com.ruoyi.business.domain.LoanInfo;
import com.ruoyi.business.processIou.service.ProcessForIouDefferredService;
import com.ruoyi.business.service.*;
import com.ruoyi.business.service.impl.BaseService;
import com.ruoyi.business.util.BigDecimalConvertUtil;
import com.ruoyi.business.util.InitDataConfig;
import com.ruoyi.common.VersionUtils;
import com.ruoyi.common.config.AwsConfig;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.*;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.enums.UserTagEnum;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.sms.domain.SmsSendData;
import com.ruoyi.sms.domain.SmsSendReq;
import com.ruoyi.sms.domain.SmsSendVo;
import com.ruoyi.sms.service.ISmsService;
import com.ruoyi.system.domain.SysFiles;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysFilesService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 登录校验方法
 *
 * @author ruoyi
 */
@Slf4j
@Component
public class AppService extends BaseService {

    private static final String REGISTER_ACTION = "register";

    private static final String INVITATION_ACTION = "invitation";

    private static final String SAVE_CONTACTS_ACTION = "saveContact";

    public static final String SYS_ACCOUNT_VERIFY_WHITELIST = "sys.account.verify.whitelist";

    private static final int EXIST_USER_COUNT = 9878;

    private static final int INIT_QUOTA = 30000;
    private static final String AMAZONAWS = "amazonaws.com";

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IAppUserService appUserService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private IAppUserContactsService appUserContactsService;

    @Autowired
    private IAppUserScoreService appUserScoreService;

    @Autowired
    private IBAppUserScoreService bUserScoreService;

    @Autowired
    private IAppFingerprintLogService appFingerprintLogService;

    @Autowired
    private IBProductService bProductService;

    @Autowired
    @Lazy
    IBLoanInfoService bLoanInfoService;

    @Autowired
    IApplyContactsService applyContactsService;

    @Autowired
    IApplyCallLogService applyCallLogService;

    @Autowired
    IApplySmsService applySmsService;

    @Autowired
    ICustTransactionSettingService custTransactionSettingService;

    @Autowired
    ICustomerInfoService customerInfoService;

    @Autowired
    IRealNameAuthService realNameAuthService;

    @Autowired
    ICreditApplyService creditApplyService;

    @Autowired
    ICreditAccountService creditAccountService;

    @Autowired
    ISysFilesService sysFilesService;

    @Autowired
    IBLoanInfoService loanInfoService;

    @Autowired
    ILoanIouService loanIouService;

    @Autowired
    ICustBankCardService custBankCardService;

    @Autowired
    ICustBaseChangeLogService custBaseChangeLogService;

    @Autowired
    ILoanOrderService loanOrderService;

    @Autowired
    IBRepaymentService bRepaymentService;

    @Autowired
    ISmsService smsService;

    @Autowired
    IAppService appService;

    @Autowired
    private IBankAccountService bankAccountService;

    @Autowired
    private RulePremiseService premiseService;

    @Autowired
    private IApplyCalendarService applyCalendarService;

    @Autowired
    ISysDictDataService dictDataService;

    @Autowired
    IProductInfoService productInfoService;

    @Autowired
    private ProductInfoMapper productInfoMapper;

    // @Autowired
    // LogAsync logAsync;

    @Autowired
    IExtIdentityResultService iExtIdentityResultService;

    @Autowired
    IBankListService iBankListService;

    @Autowired
    RedisCache redisCache;

    @Autowired
    AsyncService asyncService;

    @Autowired
    private ISysConfigService iSysConfigService;

    @Autowired
    private IBankCardService bankCardService;

    @Autowired
    private IAppUserPushService iAppUserPushService;

    @Autowired
    private IBankCodeService bankCodeService;

    @Autowired
    ICustAndonLogService iCustAndonLogService;

    @Autowired
    LoanRule loanRule;

    @Autowired
    IAppDeviceContactapplistRelativeService iAppDeviceContactapplistRelativeService;

    @Autowired
    IRaiseLimitService raiseLimitService;

    @Autowired
    IDeviceContactsService iDeviceContactsService;

    @Autowired
    private CustomerInfoMapper customerInfoMapper;

    @Autowired
    private AppUserMapper appUserMapper;

    @Autowired
    private SysConfigMapper sysConfigMapper;

    private static final String REPEAT_SUBMIT = "repeatSubmit:";

    @Autowired
    private IAppUserMarkService appUserMarkService;

    @Autowired
    DoCalCustReduce doCalCustReduce;

    @Autowired
    IWalletService walletService;

    @Autowired
    private UserCacheService userCacheService;

    @Autowired
    private IProductDeferredInfoService iProductDeferredInfoService;

    @Autowired
    private ProcessForIouDefferredService processForIouDefferredService;

    @Autowired
    private IDoRepaymentLastService doRepaymentLastService;

    @Autowired
    private InviteCodePool inviteCodePool;

    @Autowired
    private LoanIouDeferredMapper loanIouDeferredMapper;
    /**
     * 还款方式名称
     **/
    private static final String REPAY_ALL_NAME = "Repay all";
    private static final String MIN_REPAY_NAME = "Min repay";


    //获取用户积分排名
    private int getUserScoreRanking(AppUser user) {
        int recommendRanking = 0;
    	/*int recommendQuota = 0;

    	//推荐数统计增加排名
    	AppUser recommendUserListQuery = new AppUser();
    	recommendUserListQuery.setRecommendCode(user.getInviteCode());
		List<AppUser> recommendList = appUserService.selectAppUserList(recommendUserListQuery);
		if(recommendList.size()>=3) {
			recommendRanking = recommendRanking + 60;
			recommendQuota = recommendQuota + 3000;
		}else if(recommendList.size()>=1) {
			recommendRanking = recommendRanking + 20;
			recommendQuota = recommendQuota + 1000;
		}

		//通讯录授权增加
    	if(this.getHasPhoneContacts(user.getUserId())) {
    		recommendRanking = recommendRanking + 10;
			recommendQuota = recommendQuota + 1000;
    	}*/

        Integer dbRecommendRanking = bUserScoreService.getUserScoreRanking(user.getUserId());
        if (null != dbRecommendRanking) {
            recommendRanking = dbRecommendRanking;
        }
        return recommendRanking + EXIST_USER_COUNT;
    }

    //获取用户推荐总数
    private int getUserRecommendCount(AppUser user) {
        int recommendCount = 0;

        //推荐数统计增加排名
        AppUser recommendUserListQuery = new AppUser();
        recommendUserListQuery.setRecommendCode(user.getInviteCode());
        List<AppUser> recommendList = appUserService.selectAppUserList(recommendUserListQuery);
        if (recommendList.size() >= 0) {
            recommendCount = recommendList.size();
        }

        return recommendCount;
    }

    //获取用户总排队数
    private int getUserCount() {
        int count = EXIST_USER_COUNT;
        List<AppUser> list = appUserService.selectAppUserList(new AppUser());
        if (list.size() > 0) {
            count = count + list.size();
        }
        return count;
    }

    //登录身份认证
    private boolean gethasLoginResult(String userId) {
        // 更新缓存用户权限
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if (null != loginUser) {
            String hasLoginUUid = loginUser.getUsername();
            if (StringUtils.isNotBlank(hasLoginUUid) && StringUtils.isNotBlank(userId) && userId.equals(hasLoginUUid)) {
                return true;
            }
        }
        return false;
    }

    public JSONObject getHome(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String userId = null;
        if (null != dataJson.get("userId") || StringUtils.isNotBlank(dataJson.get("userId").toString())) {
            userId = dataJson.get("userId").toString();
        }

        int maxQuota = INIT_QUOTA;

        int userCount = this.getUserCount();
        rsp.put("totalQueue", userCount);

        boolean tokenResult = false;
        if (StringUtils.isNotBlank(userId)) {
            tokenResult = this.gethasLoginResult(userId);
        }

//        boolean tokenResult = this.gethasLoginResult(userId);
        //登录标记
        if (tokenResult) {
            //查找用户
            AppUser userQuery = new AppUser();
            userQuery.setUserUuid(userId);
            List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
            if (inviteCodeList.size() < 1) {
                throw new BusinessException(RspEnmu.USER_NOT_EXIST);
            }
            rsp.put("invitationCode", inviteCodeList.get(0).getInviteCode());
            int rankingNo = this.getUserScoreRanking(inviteCodeList.get(0));

            if (this.getHasPhoneContacts(inviteCodeList.get(0).getUserId())) {
                rsp.put("hasContacts", "1");
                rankingNo = rankingNo - 10;//完成通讯录授权任务
                maxQuota = maxQuota + 1000;
            }
            int recommendCount = this.getUserRecommendCount(inviteCodeList.get(0));
            if (recommendCount > 2) {
                rsp.put("hasRecommend1", "1");
                rsp.put("hasRecommend3", "1");
                rankingNo = rankingNo - 60;//完成推荐3人任务
                maxQuota = maxQuota + 3000;
            } else if (recommendCount > 0) {
                rsp.put("hasRecommend1", "1");
                rsp.put("hasRecommend3", "0");
                rankingNo = rankingNo - 20;//完成推荐1人任务
                maxQuota = maxQuota + 1000;
            } else {
                rsp.put("hasRecommend1", "0");
                rsp.put("hasRecommend3", "0");
            }
            rsp.put("rankingNo", rankingNo);
        } else {
            rsp.put("rankingNo", userCount);
            rsp.put("hasContacts", "0");
            rsp.put("hasRecommend1", "0");
            rsp.put("hasRecommend3", "0");
        }
        rsp.put("maxQuota", maxQuota);

        return rsp;
    }

    private boolean getHasPhoneContacts(Long userId) {
        AppUserContacts appUserContacts = new AppUserContacts();
        appUserContacts.setUserId(userId);
        List<AppUserContacts> userContactsList = appUserContactsService.selectAppUserContactsList(appUserContacts);
        if (userContactsList.size() > 0) {
            return true;
        }
        return false;
    }


    public JSONObject setPassword(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String password = dataJson.get("password").toString();
        String userId = dataJson.get("userId").toString();

        boolean tokenResult = this.gethasLoginResult(userId);
        //登录标记
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(userId);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);

        //状态检查
        if (!"0".equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        //对密码进行加密
        user.setPassword(bCryptPasswordEncoder.encode(password));
        appUserService.updateAppUser(user);

        //注册成功-未实名
        QueryWrapper<AppUserMark> wrapper = new QueryWrapper<AppUserMark>().eq("register_phone", user.getPhone());
        wrapper.last("limit 1");
        AppUserMark userMark = appUserMarkService.getOne(wrapper);
        //用户标签不为空，且标签是安装未注册或注册时更新标签
        if (Func.isNotEmpty(userMark)) {
            if (userMark.getFirstTag().equals("Unregistered") || userMark.getFirstTag().equals("Registered")) {
                //AppUserMark appUserMark = AppUserMark.builder().registerPhone(user.getPhone()).userId(user.getUserUuid()).build();
                asyncService.apdUserTag(AppUserMark.builder().registerPhone(user.getPhone()).userId(user.getUserUuid()).build(), UserTagEnum.REGISTERED_NOT_VERIFIED);
            }
        } else {//用户标签为空，直接添加
            //AppUserMark appUserMark = AppUserMark.builder().userId(user.getUserUuid()).build();
            asyncService.apdUserTag(AppUserMark.builder().userId(user.getUserUuid()).build(), UserTagEnum.REGISTERED_NOT_VERIFIED);
        }
        return rsp;
    }

    public JSONObject login(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String countryCode = dataJson.get("countryCode").toString();
        String phone = dataJson.get("phone").toString();
        String password = dataJson.get("password").toString();

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setCountryCode(countryCode);
        userQuery.setPhone(phone);
        userQuery.setState("0");
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);

        //判断密码是否正确
        if (!bCryptPasswordEncoder.matches(password, user.getPassword())) {
            throw new BusinessException(RspEnmu.USER_PASSWORD_ERR);
        }

        //增加记录设备详细信息记录日志
        JSONObject deviceInfo = dataJson.getJSONObject("deviceInfo");
        if (null != deviceInfo) {
            //根据用户获取客户id
            /*String custNo = "";
            CustomerInfo custQuery = new CustomerInfo();
            custQuery.setUserId(user.getUserUuid());
            List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
            if (customerInfoList.size() > 0) {
                CustomerInfo custInfo = customerInfoList.get(0);
                custNo = custInfo.getCustNo();
            }*/
            appService.saveAppDeviceInfo(user.getUserUuid(), null, BizConstants.ACTION_TYPE_PASSWORD_LOGIN, null, deviceInfo);
        }

        //状态检查
        if (!"0".equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        //生成token并返回
        String token = this.genAppToken(user.getUserUuid());
        iAppDeviceContactapplistRelativeService.copyData(deviceInfo.getString("newFingerprint"), user.getUserUuid());
        rsp.put("token", token);
        rsp.put("userId", user.getUserUuid());

        return rsp;
    }

    //注册
    public JSONObject register(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String countryCode = dataJson.get("countryCode").toString();
        String phone = dataJson.get("phone").toString();
        String verificationCode = dataJson.get("verificationCode").toString();
//        String reqUuid = dataJson.get("uuid").toString();
        String reqUuid = dataJson.get("uuid") == null ? null : dataJson.get("uuid").toString();
        String smsType = dataJson.get("smsType").toString();
        String fingerprint = dataJson.get("fingerprint") == null ? null : dataJson.get("fingerprint").toString();
        String recommendCode = dataJson.getString("recommendCode");
        String linkRecommendCode = dataJson.getString("linkRecommendCode");
        String channel = dataJson.get("channel")== null ? null : dataJson.get("channel").toString();
        if (dataJson.containsKey("noticeType") && dataJson.getString("noticeType") != null
                && dataJson.getString("noticeType").equals("whatsApp")) {
            log.info("------ whatsApp   验证码不在此校验");
        } else {
            //短信验证码校验逻辑
            this.checkVerifiCode(SmsSendVo.builder().verifyCode(verificationCode).countryCode(countryCode.replace("+", "")).phoneNumber(phone).smsType(smsType).uuid(reqUuid).build());
        }


        //用户手机号是否有效
        AppUser appUser = appUserMapper.selectUser(phone);
        if (appUser != null) {
            throw new BusinessException(RspEnmu.USER_EXIST);
        }
//        /**
//         * 注册次数大于3并且重新注册时间间隔<8抛出异常
//         */
        ////        //用户手机号注册全部次数
////        int userallcount=appUserMapper.countall(phone);
//        //检查用户上次注销最近时间
//        String cancellationTime = appUserReasonMapper.getCancellationTime(phone).toString();
//        //获取当前时间
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        String nowDate = sdf.format(System.currentTimeMillis());
//        //计算当前时间与最新更新时间差
//        SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//        long nowTime=1;
//        long updateTime=1;
//        try {
//             nowTime = simpleFormat.parse(nowDate).getTime();
//             updateTime = simpleFormat.parse(cancellationTime).getTime();
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
//        if (userallcount > 3&&((nowTime - updateTime) / (1000 * 60 * 60 ))<8)
//        {
//            throw new BusinessException(RspEnmu.Operation_Is_Too_Frequent);
//        }

//        检查用户注册次数
//        AppUser userExistQuery = new AppUser();
//        userExistQuery.setCountryCode(countryCode);
//        userExistQuery.setPhone(phone);
//        List<AppUser> existList = appUserService.selectAppUserList(userExistQuery);
//        if (existList.size() > 0) {
//            throw new BusinessException(RspEnmu.USER_EXIST);
//        }
        //校验邀请码
        recommendCode = this.inviteCodeValid(phone, recommendCode, linkRecommendCode);

        //创建新用户并保存
        String userUuid = UUID.fastUUID().toString().replaceAll("-", "");
        AppUser user = new AppUser();
        user.setCountryCode(countryCode);
        user.setPhone(phone);
        user.setUserUuid(userUuid);
        user.setInviteCode(inviteCodePool.assignInviteCode(true));
        user.setRecommendCode(recommendCode);
        appUserService.insertAppUser(user);

        // 创建客户信息
        String custNo = IdUtils.generateCustNo();
        CustomerInfo custInfo = new CustomerInfo();
        custInfo.setUserId(userUuid);
        custInfo.setCustNo(custNo);
        customerInfoService.insertCustomerInfo(custInfo);

        // 缓存客户信息到redis
        userCacheService.getUserCacheInfo(userUuid);

        // 创建钱包账户
        initWalletAccount(custNo);

        //增加记录设备详细信息记录日志
        JSONObject deviceInfo = dataJson.getJSONObject("deviceInfo");
        if (null != deviceInfo) {
            //根据用户获取客户id
            /*String custNo = "";
            CustomerInfo custQuery = new CustomerInfo();
            custQuery.setUserId(user.getUserUuid());
            List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
            if (customerInfoList.size() > 0) {
                CustomerInfo custInfo = customerInfoList.get(0);
                custNo = custInfo.getCustNo();
            }*/
            appService.saveAppDeviceInfo(user.getUserUuid(), null, BizConstants.ACTION_TYPE_REGISTER, null, deviceInfo);
        }

        //生成token并返回
        String token = this.genAppToken(user.getUserUuid());
        iAppDeviceContactapplistRelativeService.copyData(deviceInfo.getString("newFingerprint"), user.getUserUuid());

        rsp.put("token", token);
        rsp.put("userId", user.getUserUuid());

        //更新注册积分
        this.updateUserScore(user.getUserId(), REGISTER_ACTION, null);

        //推荐人代码推荐加分
        if (Func.isNotEmpty(recommendCode)) {
            //根据推荐代码查询用户
            AppUser userQuery = new AppUser();
            userQuery.setInviteCode(recommendCode);
            userQuery.setInviteCodeStatus("1");
            List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
            if (inviteCodeList.size() > 0) {
                AppUser recommendUser = inviteCodeList.get(0);
                //更新注册积分
                this.updateUserScore(recommendUser.getUserId(), INVITATION_ACTION, -3000L);

                //发送邀请成功短信
                JSONObject param = new JSONObject();
                param.put("inviterNickname", recommendUser.getNickName());
                param.put("advanceCredit", iSysConfigService.selectConfigByKey("advance_credit"));
                SmsSendData smsData = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE)
                        .phoneNumber(user.getPhone()).countryCode(user.getCountryCode())
                        .smsParam(param).smsType(BizConstants.SMS_TYPE_INVITER_REGISTER).build();
                asyncService.sendSms(smsData);
            }
        }
        //注册成功校验用户是否是Crs白名单用户
        asyncService.checkChannel(phone,channel);

        //注册成功-无密码标签
        AppUserMark appUserMark = AppUserMark.builder().userId(custInfo.getUserId()).custNo(custInfo.getCustNo()).registerPhone(phone).build();
        asyncService.apdUserTag(appUserMark, UserTagEnum.REGISTERED_NOT_PASSWORD);
        return rsp;
    }

    private void initWalletAccount(String custNo) {
        walletService.initWalletAccount(custNo);
    }

    //注册
    public JSONObject smsLogin(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String reqUuid = dataJson.get("uuid").toString();
        String smsType = dataJson.get("smsType").toString();
        String countryCode = dataJson.get("countryCode").toString();
        String phone = dataJson.get("phone").toString();
        String verificationCode = dataJson.get("verificationCode").toString();
        String fingerprint = dataJson.get("fingerprint") == null ? null : dataJson.get("fingerprint").toString();
        Integer type = dataJson.getInteger("type")==null?1:dataJson.getInteger("type");

        //whatapps验证码校验
        if(2==type){
            //设备操作记录
            if (StringUtils.isNotBlank(fingerprint)) {
                AppFingerprintLog appFingerprintLog = new AppFingerprintLog();
                appFingerprintLog.setActionType(smsType + "_SMS_CHECK");
                appFingerprintLog.setFingerprint(fingerprint);
                appFingerprintLogService.insertAppFingerprintLog(appFingerprintLog);
            }
            boolean isValid = smsService.verifyWhatsAppCode(SmsSendData.builder()
                    .phoneNumber(phone).verifyCode(verificationCode).build());
            if (!isValid) {
                throw new BusinessException(RspEnmu.SMS_CODE_ERR);
            }
        }else {
            //短信验证码校验逻辑
            this.checkVerifiCode(SmsSendVo.builder().verifyCode(verificationCode).countryCode(countryCode.replace("+", "")).phoneNumber(phone).smsType(smsType).uuid(reqUuid).build());
        }


        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setCountryCode(countryCode);
        userQuery.setPhone(phone);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);

        //增加记录设备详细信息记录日志
        JSONObject deviceInfo = dataJson.getJSONObject("deviceInfo");
        if (null != deviceInfo) {
            //根据用户获取客户id
            /*String custNo = "";
            CustomerInfo custQuery = new CustomerInfo();
            custQuery.setUserId(user.getUserUuid());
            List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
            if (customerInfoList.size() > 0) {
                CustomerInfo custInfo = customerInfoList.get(0);
                custNo = custInfo.getCustNo();
            }*/
            appService.saveAppDeviceInfo(user.getUserUuid(), null, BizConstants.ACTION_TYPE_SMS_LOGIN, null, deviceInfo);
        }

        //状态检查
        if (!"0".equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        //生成token并返回
        String token = this.genAppToken(user.getUserUuid());
        iAppDeviceContactapplistRelativeService.copyData(deviceInfo.getString("newFingerprint"), user.getUserUuid());

        rsp.put("token", token);
        rsp.put("userId", user.getUserUuid());
        return rsp;
    }

    public void loginOut(JSONObject dataJson) {
//        boolean tokenResult = this.gethasLoginResult(dataJson.get("userId").toString());
//        if (tokenResult) {
        this.loginOutAppUser();
//        }
    }

    private void loginOutAppUser() {
        tokenService.delAppLoginUser(ServletUtils.getRequest());
    }


    //生成token
    private String genAppToken(String userUuid) {
        LoginUser appuser = new LoginUser();
        appuser.setLoginTime(System.currentTimeMillis());
        SysUser user = new SysUser();
        user.setUserName(userUuid);
        appuser.setUser(user);
        return tokenService.createAppToken(appuser);
    }

    //短信验证码校验
    private void checkVerifiCode(SmsSendVo smsVo) {
        //设备操作记录
        if (StringUtils.isNotBlank(smsVo.getFingerprint())) {
            AppFingerprintLog appFingerprintLog = new AppFingerprintLog();
            appFingerprintLog.setActionType(smsVo.getSmsType() + "_SMS_CHECK");
            appFingerprintLog.setFingerprint(smsVo.getFingerprint());
            appFingerprintLogService.insertAppFingerprintLog(appFingerprintLog);
        }

        smsService.verifySmsCode(smsVo);

//    	String redisKey = BizConstants.SMS_CODE + "-" + smsType + "-" + countryCode + "-" + phone + "-" + reqUuid;
//        //redisCache.setCacheObject(redisKey, verificationCode, 3000, TimeUnit.SECONDS);
//    	Object cacheObj = redisCache.getCacheObject(redisKey);
//    	if(null==cacheObj) {
//    		throw new BusinessException(RspEnmu.SMS_CODE_EXPRIRE);
//    	}
//
//    	String captcha = (String) cacheObj;
//    	if(!verificationCode.equals(captcha)) {
//    		throw new BusinessException(RspEnmu.SMS_CODE_ERR);
//		}
//    	redisCache.deleteObject(redisKey);
    }

    //更新用户积分
    private void updateUserScore(long userId, String type, Long score) {
        AppUserScore appUserScore = new AppUserScore();
        appUserScore.setUserId(userId);
        appUserScore.setType(type);
        appUserScore.setState(UserConstants.NORMAL);

        if (REGISTER_ACTION.equals(type)) {
            Date now = new Date();
            String yearStr = DateFormatUtils.format(now, "yyyy");
            int yearInt = Integer.parseInt(yearStr) - 2020;
            String scoreStr = DateFormatUtils.format(now, "MdHHmmss");
            scoreStr = yearInt + scoreStr;
            appUserScore.setScore(Long.parseLong(scoreStr));
        } else {
            if (null != score) {
                appUserScore.setScore(score);
            } else {
                appUserScore.setScore(0L);
            }
        }
        appUserScoreService.insertAppUserScore(appUserScore);
    }


    public JSONArray getProductList() {
        JSONArray rsp = new JSONArray();

        BigDecimal creditAmt = BigDecimal.ZERO;
        CustomerInfo customerInfo = new CustomerInfo();
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if (loginUser != null) {
            String userUUid = loginUser.getUsername();
            //根据用户获取客户id
            customerInfo.setUserId(userUUid);
            List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(customerInfo);
            if (customerInfoList.size() == 1) {
                customerInfo = customerInfoList.get(0);
                CreditAccount creditAccount = new CreditAccount();
                creditAccount.setCustNo(customerInfo.getCustNo());
                creditAccount.setState(UserConstants.BUSINESS_NORMAL);
                List<CreditAccount> selectCreditAccountList = creditAccountService.selectCreditAccountList(creditAccount);
                if (selectCreditAccountList.size() == 1) {
                    creditAccount = selectCreditAccountList.get(0);
                    creditAmt = creditAccount.getCreditLine();
                }
            }
            //BigDecimal pat8 = new BigDecimal("0.8");
        }

        BigDecimal pat = new BigDecimal("100");
        String appVersion = this.getAppVersion();
        String appGpReviewVersion = getDictLabel("biz_switch", "app_gp_review_version");
        log.info("appVersion = {}, appGpReviewVersion = {}", appVersion, appGpReviewVersion);
        //获取谷歌白名单验证账号
        if (this.appGpReviewSwitch()) {
            String sysConfigValue = getSysConfigValueByKey(SYS_ACCOUNT_VERIFY_WHITELIST);
            if ((formatAppVersion(appVersion) == formatAppVersion(appGpReviewVersion))
                    || (null != sysConfigValue && this.getUserOnline() && sysConfigValue.contains(this.getAppUser().getPhone()))
            ) {
                ProductInfo p = bProductService.getAppGpReviewProduct();
                JSONObject jp = formatProduct(creditAmt, pat, p);
                rsp.add(jp);
                return rsp;
            }
        }


        List<ProductInfo> list = bProductService.getActiveProductList(customerInfo.getCreditRating());

        for (ProductInfo p : list) {
            JSONObject jp = formatProduct(creditAmt, pat, p);
            if (jp == null) continue;
            rsp.add(jp);
        }

        return rsp;
    }

    private JSONObject formatProduct(BigDecimal creditAmt, BigDecimal pat, ProductInfo p) {
        JSONObject jp = new JSONObject();
        jp.put("productId", p.getId());
        jp.put("productCode", p.getProductCode());
        jp.put("productName", p.getProductName());
        jp.put("unit", p.getUnit());
        jp.put("minQuota", p.getMinQuota().setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
        jp.put("periodNum", p.getPeriodNum());
        if (null != p.getInterestRate()) {
            Double interestRate = p.getInterestRate().multiply(pat).doubleValue();
            String interestRateStr = interestRate.toString();
            if (null != interestRateStr && interestRateStr.indexOf(".") > 0) {
                interestRateStr = interestRateStr.replaceAll("0+?$", "");//去掉多余的0
                interestRateStr = interestRateStr.replaceAll("[.]$", "");//如最后一位是.则去掉
            }
            jp.put("interestRate", interestRateStr + "%");
        } else {
            return null;
        }
        if (creditAmt.compareTo(BigDecimal.ZERO) == 1) {//如果金额大于0
            BigDecimal creditScale = p.getCreditScale();
            jp.put("maxQuota", creditAmt.multiply(creditScale).setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
            /*if (p.getProductCode().indexOf("_0.8") > 1) {
                jp.put("maxQuota", creditAmt.multiply(pat).setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
            } else {
                jp.put("maxQuota", creditAmt.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
            }*/
        } else {
            jp.put("maxQuota", p.getMaxQuota().setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
        }
        return jp;
    }

    //客户首页接口
    public JSONObject getUserHome(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        rsp.put("creditRejectDays", 0);
        rsp.put("andonSecond", -1);

        String userUUId = null;
        if (null != dataJson.get("userId") && StringUtils.isNotBlank(dataJson.get("userId").toString())) {
            userUUId = dataJson.get("userId").toString();
        }
        //根据键名查询参数配置信息
        String upToDays = iSysConfigService.selectConfigByKey("up_to_days");

        String[] split = upToDays.split(",");

        String minimum = split[4];
        String unMinimum = split[3];
        String realUpToDays = split[2];
        String unRealUpToDays = split[1];
        String upToDaysVersion = split[0];
        String appVersion = getAppVersion();
        log.info("当前app版本{}", appVersion);
        if (appVersion.equals(upToDaysVersion)) {
            rsp.put("upToDays", unRealUpToDays);
            rsp.put("minimum", unMinimum);
        } else {
            rsp.put("upToDays", realUpToDays);
            rsp.put("minimum", minimum);
        }
        //判断是否需要白名单校验
        if (appGpReviewSwitch()) {
            //获取谷歌白名单验证账号
            String sysConfigValue = getSysConfigValueByKey(SYS_ACCOUNT_VERIFY_WHITELIST);
            if (this.getUserOnline() && null != sysConfigValue && sysConfigValue.contains(this.getAppUser().getPhone())) {
                rsp.put("upToDays", unRealUpToDays);
                rsp.put("minimum", unMinimum);
            }
        }

        if (StringUtils.isBlank(userUUId)) {
            try {
                userUUId = getUserId();
            } catch (Exception e) {
                log.warn("userUUId 为空");
            }
        }

        log.info("用户 UserID = {}", userUUId);

        //主动提额信息
        rsp.put("promotion", raiseLimitService.getPromotionJson(Func.isEmpty(userUUId) ? "" : getCustNo()));

        //是否登录成功
        boolean tokenResult = false;
        if (StringUtils.isNotBlank(userUUId)) {
            tokenResult = this.gethasLoginResult(userUUId);
        }

        if (!tokenResult) {
            rsp.put("hasLogin", "0");
            return rsp;
        }
        rsp.put("hasLogin", "1");
        //未实名 或者 未授信

        //实名
        //根据客户信息获取实名信息获取结果
        RealNameAuth realNameQuery = new RealNameAuth();
        realNameQuery.setUserId(userUUId);
        realNameQuery.setState(UserConstants.BUSINESS_NORMAL);
        List<RealNameAuth> realNameList = realNameAuthService.selectRealNameAuthList(realNameQuery);
        if (realNameList.size() < 1) {
            rsp.put("hasRealName", "0");
            //渠道邀请卡片
            JSONObject channelCard = buildChannelCard(null);
            if (channelCard != null) {
                rsp.put("channelCard", channelCard);
            }
            rsp.put("firstName", "Welcome to LinkCredit!");
            return rsp;
        }

        rsp.put("hasRealName", "1");
        //获取用户信息
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("bvn", DesensitizeUtils.around(realNameList.get(0).getBvnAccount(), 3, 4));
        userInfo.put("name", realNameList.get(0).getFirstName() + " " + (realNameList.get(0).getMiddleName() == null ? "" : realNameList.get(0).getMiddleName() + " ") + realNameList.get(0).getLastName());
        userInfo.put("gender", realNameList.get(0).getGender());
        userInfo.put("birthDate", realNameList.get(0).getBirthDate());
        rsp.put("userInfo", userInfo);

        //找到银行账户
        Map<String, Object> bankInfo = new HashMap<>();
        RealNameAuth realNameAuth = realNameList.get(0);
        BankCode bankCode = new BankCode();
        bankCode.setPaystackBankCode(realNameAuth.getBankCode());
        List<BankCode> bankCodes = bankCodeService.selectBankCodeList(bankCode);
        if (bankCodes.size() > 0) {
            bankInfo.put("bankName", bankCodes.get(0).getPaystackBankName());
        }
        //实名后Account可能为空

        BankAccount bankAccount = new BankAccount();
        bankAccount.setCustNo(realNameList.get(0).getCustNo());
        bankAccount.setIsDefault("1");
        List<BankAccountVo> bankAccountVos = bankAccountService.selectBankAccountAndNameList(bankAccount);

        if (bankAccountVos.size() > 0 && Func.isNotEmpty(bankAccountVos.get(0).getAccountNumber())) {
            bankInfo.put("bankCode", DesensitizeUtils.right(bankAccountVos.get(0).getAccountNumber(), 4));
            //AccountNumber
            bankInfo.put("accountNumber", DesensitizeUtils.right(bankAccountVos.get(0).getAccountNumber(), 4));
        }

        rsp.put("bankInfo", bankInfo);
        //实名通过获取用户firstName
        String firstName = realNameAuthService.selectFirstName(getCustNo());
        rsp.put("firstName", "Hello " + firstName + "!");
        //最近一笔申请
        CreditApply creditApply = new CreditApply();
        creditApply.setUserId(userUUId);
        creditApply.setState(UserConstants.BUSINESS_NORMAL);
        List<CreditApply> applyList = creditApplyService.selectCreditApplyList(creditApply);
        //未授信
        if (applyList.size() < 1) {
            rsp.put("applyNo", "");
            //渠道邀请卡片
            JSONObject channelCard = buildChannelCard(null);
            if (channelCard != null) {
                rsp.put("channelCard", channelCard);
            }
            return rsp;
        }
        //申请编号和状态
        CreditApply lastApply = applyList.get(0);
        String lastApplyNo = lastApply.getApplySerialNo();

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        //先判断状态是否已拒绝
        if (ApplyConstants.APPLY_STATE_REJECT == lastApply.getApplyStatus()) {
            //计算审批结果和当前时间相差天数
            int creditRejectDays = 0;
            try {
                long startDateTime = dateFormat.parse(dateFormat.format(lastApply.getUpdateTime())).getTime();
                long endDateTime = dateFormat.parse(dateFormat.format(new Date())).getTime();
                creditRejectDays = (int) ((endDateTime - startDateTime) / (1000 * 3600 * 24));
            } catch (ParseException e) {
                log.error("==计算申请拒绝更新时间是否超出30天异常，申请编号{}==", lastApply.getApplySerialNo(), e);
            }

            int freezeDate = 30;
            if (Func.isNotEmpty(lastApply.getFreezeDate())) {
                freezeDate = Integer.valueOf(lastApply.getFreezeDate());
            }

            if (creditRejectDays >= freezeDate) {
                rsp.put("applyNo", "");
                return rsp;
            }

            if (freezeDate - creditRejectDays > 0) {
                rsp.put("applyNo", lastApplyNo);
                rsp.put("applyStatus", lastApply.getApplyStatus());
                rsp.put("creditRejectDays", freezeDate - creditRejectDays);
                rsp.put("creditApplyDate", lastApply.getUpdateTime());
                rsp.put("email", lastApply.getEmail());
                return rsp;
            }
        }

        if (lastApply.getApplyStatus() != ApplyConstants.APPLY_STATE_REJECT && lastApply.getApplyStatus() != ApplyConstants.APPLY_STATE_PASS) {
            rsp.put("applyStatus", lastApply.getApplyStatus());
            rsp.put("creditApplyDate", lastApply.getUpdateTime());
            rsp.put("email", lastApply.getEmail());
            QueryWrapper<CustAndonLog> custAndonLogWrapper = new QueryWrapper<>();
            custAndonLogWrapper.eq("relation_sn", lastApply.getApplySerialNo());
            custAndonLogWrapper.eq("cust_no", lastApply.getCustNo());
            custAndonLogWrapper.eq("type", BizConstants.ANDON_TYPE_CREDIT);
            CustAndonLog custAndonLog = iCustAndonLogService.getOne(custAndonLogWrapper);
            if (custAndonLog == null) {
                double dateDiff = DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_SECOND, new Date(), lastApply.getCreateTime());
                rsp.put("andonSecond", new BigDecimal((60 * 5 - dateDiff) * 1000 < 0 ? 0 : (60 * 5 - dateDiff) * 1000).intValue());
            }

            return rsp;
        }

        //授信通过获取账户信息
        if (ApplyConstants.APPLY_STATE_PASS == lastApply.getApplyStatus()) {
            rsp.put("applyNo", lastApplyNo);
            rsp.put("applyStatus", lastApply.getApplyStatus());
            rsp.put("creditApplyDate", lastApply.getUpdateTime());
            rsp.put("email", lastApply.getEmail());

            //授信通过获取客户信用评级
            String creditRating = customerInfoMapper.selectCreditRating(getCustNo());
            String customerRating = iSysConfigService.selectConfigKey(creditRating);
            rsp.put("customerRating", customerRating);
            //授信通过获取客户金融产品标签
            ProductInfo tags = productInfoMapper.getTags(creditRating);
            List<String> result = new ArrayList<>();
            if (!StringUtils.isNull(tags)) {
                if(!StringUtils.isEmpty(tags.getTags())) {
                    if (tags.getTags().contains("-1") && tags.getTags().contains("-2") && tags.getTags().contains("%")) {
                        result.add(Constants.INTEREST);
                        result.add(Constants.FLEXIBLE_REPAY);
                        rsp.put("classInterest", result);
                    }
                    else if(tags.getTags().contains("-1")&&tags.getTags().contains("%")){
                        result.add(Constants.INTEREST);
                        rsp.put("classInterest", result);
                    }
                    else if(tags.getTags().contains("-1")&&tags.getTags().contains("-2")){
                        result.add(Constants.INTEREST);
                        result.add(Constants.FLEXIBLE_REPAY);
                        rsp.put("classInterest", result);
                    }
                    else if(tags.getTags().equals("-1")){
                        result.add(Constants.INTEREST);
                        rsp.put("classInterest", result);
                    }
                    else if (tags.getTags().contains("%") && tags.getTags().contains("-2")) {
                        //产品展示利率
                        BigDecimal showInterestRate = tags.getShowInterestRate();
                        //产品实际利率
                        BigDecimal interestRate = tags.getInterestRate();
                        int show = (((showInterestRate.subtract(interestRate)).divide(showInterestRate,2,BigDecimal.ROUND_HALF_UP)).multiply(BigDecimal.valueOf(100))).intValue();
                        result.add(show + "%" + Constants.DISCOUNT);
                        result.add(Constants.FLEXIBLE_REPAY);
                        rsp.put("classInterest", result);
                    }
                    else if (tags.getTags().contains("%")) {
                        //产品展示利率
                        BigDecimal showInterestRate = tags.getShowInterestRate();
                        //产品实际利率
                        BigDecimal interestRate = tags.getInterestRate();
                        int show = (((showInterestRate.subtract(interestRate)).divide(showInterestRate,2,BigDecimal.ROUND_HALF_UP)).multiply(BigDecimal.valueOf(100))).intValue();
                        result.add(show + "%" + Constants.DISCOUNT);
                        if (tags.getTags().equals("-2")){
                            result.add(Constants.FLEXIBLE_REPAY);
                        }
                        rsp.put("classInterest", result);
                    }
                    else if (tags.getTags().equals("-2")) {
                        result.add(Constants.FLEXIBLE_REPAY);
                        rsp.put("classInterest", result);
                    }
                }else{
                    rsp.put("classInterest", result);
                }
            } else {
                rsp.put("classInterest", result);
            }

            //根据用户获取客户id
            CustomerInfo custQuery = new CustomerInfo();
            custQuery.setUserId(userUUId);
            List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
            if (customerInfoList.size() < 1) {
                throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
            }
            CustomerInfo custInfo = customerInfoList.get(0);
            String custNo = custInfo.getCustNo();

            CreditAccount creditAccount = new CreditAccount();
            creditAccount.setCustNo(custNo);
            creditAccount.setState(UserConstants.BUSINESS_NORMAL);
            List<CreditAccount> creditAccountList = creditAccountService.selectCreditAccountList(creditAccount);
            if (CollectionUtils.isEmpty(creditAccountList)) {
                rsp.put("hasLoanOrder", "0");
                return rsp;
                //throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
            }

            creditAccount = creditAccountList.get(0);

            //授信额度
            BigDecimal creditQuota = creditAccount.getCreditLine();
            rsp.put("creditQuota", creditQuota);

            //冻结额度
            BigDecimal frozenQuota = creditAccount.getFrozenQuota();
            if (null == frozenQuota) {
                frozenQuota = new BigDecimal(0);
            }

            //在贷额度
            BigDecimal loanQuota = creditAccount.getLoanQuota();
            if (null == loanQuota) {
                loanQuota = new BigDecimal(0);
            }

            //已借额度
            BigDecimal borrowedQuota = loanQuota.add(frozenQuota);
            rsp.put("borrowedQuota", borrowedQuota);

            //可用额度
            BigDecimal availableQuota = creditQuota.subtract(borrowedQuota);
            rsp.put("availableQuota", availableQuota.doubleValue() <= 0 ? BigDecimal.ZERO : availableQuota);

            // 可提现额度比例
            BigDecimal loanQuotaRatio = BigDecimal.ONE;
            boolean bindCardFlag = checkBindCardFlag(userUUId);
            if (!bindCardFlag) {
                loanQuotaRatio = BigDecimal.valueOf(Double.valueOf(dictDataService.selectDictLabel("loan_settings", "loan_quota_ratio")));
            }
            rsp.put("loanQuotaRatio", loanQuotaRatio);

            //查询是否有借款申请记录判断是否提现
            LoanOrder loanOrder = new LoanOrder();
            loanOrder.setCustNo(custNo);
            loanOrder.setState(BizConstants.BIZ_STATUS_1);
            List<LoanOrder> loanOrderList = loanOrderService.selectLoanOrderList(loanOrder);
            if (!CollectionUtils.isEmpty(loanOrderList)) {
                rsp.put("hasLoanOrder", "1");

                int loanRejectDays = 0;
                LoanOrder order = loanOrderList.get(0);
                int loanStatus = order.getLoanStatus();
                rsp.put("isScore", false);
                if (loanStatus == 0) {
                    try {
                        long startDateTime = dateFormat.parse(dateFormat.format(order.getUpdateTime())).getTime();
                        long endDateTime = dateFormat.parse(dateFormat.format(new Date())).getTime();
                        loanRejectDays = (int) ((endDateTime - startDateTime) / (1000 * 3600 * 24));
                    } catch (ParseException e) {
                        log.error("==计算提现拒绝更新时间是否超出7天异常，申请编号{}==", order.getLoanSerialNo(), e);
                    }
                    int freezeDate = 7;
                    if (Func.isNotEmpty(order.getFreezeDate())) {
                        freezeDate = Integer.valueOf(order.getFreezeDate());
                    }

                    if (freezeDate - loanRejectDays > 0) {
                        rsp.put("loanStatus", loanStatus);
                        rsp.put("loanRejectDays", freezeDate - loanRejectDays);
                    }
                } else {

                    QueryWrapper<CustAndonLog> custAndonLogWrapper = new QueryWrapper<>();
                    custAndonLogWrapper.eq("relation_sn", order.getLoanSerialNo());
                    custAndonLogWrapper.eq("cust_no", order.getCustNo());
                    custAndonLogWrapper.eq("type", BizConstants.ANDON_TYPE_LOAN);
                    CustAndonLog custAndonLog = iCustAndonLogService.getOne(custAndonLogWrapper);
                    if (custAndonLog == null) {
                        double dateDiff = DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_SECOND, new Date(), order.getCreateTime());
                        rsp.put("andonSecond", new BigDecimal((60 * 5 - dateDiff) * 1000 < 0 ? 0 : (60 * 5 - dateDiff) * 1000).intValue());
                    }
                    rsp.put("loanStatus", loanStatus);
                }
            } else {

                rsp.put("hasLoanOrder", "0");
                //授信未提现 授信成功时间 至今3天 -> 展示提额卡片
                Double dfDate = Func.dayDifference(lastApply.getUpdateTime());

                if (Func.isNotEmpty(custInfo.getPreLine()) && new BigDecimal(custInfo.getPreLine()).compareTo(BigDecimal.ZERO) > 0 && dfDate >= 3) {
                    rsp.put("predictedQuota", custInfo.getPreLine());
                } else {
                    //小于3天 判断是否展示邀请卡片
                    JSONObject channelCard = buildChannelCard(creditAccount);
                    if (channelCard != null) {
                        rsp.put("channelCard", channelCard);
                    }
                }
            }

            LoanIou loanIou = new LoanIou();
            loanIou.setCustNo(custNo);
            loanIou.setState(BizConstants.BIZ_STATUS_1);
            List<LoanIou> loanIouList = loanIouService.selectLoanIouList(loanIou);
            if (!CollectionUtils.isEmpty(loanIouList)) {
                rsp.put("loanDeferredShow",this.loanDeferredShow(loanIouList));
                boolean isOverdue = loanIouList.stream().anyMatch(p -> p.getIouStatus() == 2);
                boolean isOutStanding = loanIouList.stream().anyMatch(p -> p.getIouStatus() == 0);


                if (Func.isNotEmpty(custInfo.getPreLine()) && new BigDecimal(custInfo.getPreLine()).compareTo(BigDecimal.ZERO) > 0 && (isOverdue || isOutStanding)) {
                    rsp.put("predictedQuota", custInfo.getPreLine());
                }

                rsp.put("isScore", false);
                rsp.put("isOutStanding", isOutStanding ? "1" : "0");
                if (isOutStanding) {
                    //推送消息
                    AppUserPush appUserPush = new AppUserPush();
                    appUserPush.setIsSend(0);
                    appUserPush.setUserId(userUUId);
                    appUserPush.setState(UserConstants.BUSINESS_NORMAL);
                    appUserPush.setPushType(AppUserPush.PUSH_TYPE_SCORE);
                    List<AppUserPush> appUserPushes = iAppUserPushService.selectAppUserPushList(appUserPush);
                    if (appUserPushes.size() > 0) {
                        rsp.put("isScore", true);
                        String homeScoreTitle = iSysConfigService.selectConfigByKey("home_score_title");
                        String homeScoreContent = iSysConfigService.selectConfigByKey("home_score_content");
                        rsp.put("scoreTitle", homeScoreTitle);
                        rsp.put("scoreContent", homeScoreContent);
                        appUserPushes.get(0).setIsSend(1);
                        appUserPushes.get(0).setPushUrl(AppUserPush.PUSH_URL_HOME);
                        iAppUserPushService.updateAppUserPush(appUserPushes.get(0));
                    }
                }
                rsp.put("isOverdue", isOverdue ? "1" : "0");
                if (isOverdue) {
                    List<LoanIou> overdueIouList = loanIouList.stream().filter(p -> p.getIouStatus() == 2).collect(Collectors.toList());
                    BigDecimal overdueTotalAmt = BigDecimal.ZERO;
//                            overdueIouList.stream().forEach(p -> overdueTotalAmt.add(p.getLoanPrincipal()).add(p.getServiceFee()).add(p.getLoanInterest()).add(p.getLateFee())
//                                    .subtract(p.getRepaidPrincipal()).subtract(p.getRepaidServiceFee()).subtract(p.getRepaidInterest()).subtract(p.getRepaidLateFee()).subtract(p.getFeeRemissionAmt()));

                    for (int i = 0; i < overdueIouList.size(); i++) {
                        overdueTotalAmt = overdueTotalAmt.add(overdueIouList.get(i).getLoanPrincipal()).add(overdueIouList.get(i).getServiceFee()).add(overdueIouList.get(i).getLoanInterest()).add(overdueIouList.get(i).getLateFee());
                        overdueTotalAmt = overdueTotalAmt.subtract(overdueIouList.get(i).getRepaidPrincipal().add(overdueIouList.get(i).getRepaidServiceFee()).add(overdueIouList.get(i).getRepaidInterest()).add(overdueIouList.get(i).getRepaidLateFee()).add(overdueIouList.get(i).getFeeRemissionAmt()));
                    }
//                            overdueTotalAmt = overdueIouList.get(0).getLoanPrincipal().add(overdueIouList.get(0).getServiceFee()).add(overdueIouList.get(0).getLoanInterest()).add(overdueIouList.get(0).getLateFee());
//                            overdueTotalAmt = overdueIouList.get(0).getRepaidPrincipal().add(overdueIouList.get(0).getRepaidServiceFee()).add(overdueIouList.get(0).getRepaidInterest()).add(overdueIouList.get(0).getRepaidLateFee()).add(overdueIouList.get(0).getFeeRemissionAmt());

                    rsp.put("overdueTotalAmt", overdueTotalAmt);
                    rsp.put("maximumOverdue", bLoanInfoService.getCurrentOverdue(custNo));
                }

                boolean repayIn3Day = loanIouList.stream().anyMatch(p -> p.getIouStatus() == 0 && DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_DAY, DateUtils.dateTime(DateUtils.YYYY_MM_DD_SLASH, p.getRepayDate()), new Date()) < 3);
//                        boolean repayIn3Day = false;
//                        for (int i = 0;i<loanIouList.size();i++){
//                            if(loanIouList.get(i).getIouStatus()==0 && DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_DAY, new Date(), DateUtils.dateTime(DateUtils.YYYY_MM_DD_SLASH, loanIouList.get(i).getRepayDate())) < 3){
//                                log.info("QQQWWWEEE{}",loanIouList.get(i).getId());
//                                repayIn3Day = true;
//                                break;
//                            }
//                        }
                //log.info("QQQWWWEEE{}",repayIn3Day);
                rsp.put("repayIn3Day", repayIn3Day ? "1" : "0");
                if (repayIn3Day) {
                    List<LoanIou> repayIn3DayIouList = loanIouList.stream().filter(
                                    p -> p.getIouStatus() == 0 && DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_DAY, DateUtils.dateTime(DateUtils.YYYY_MM_DD_SLASH, p.getRepayDate()), new Date()) < 3)
                            .collect(Collectors.toList());
                    BigDecimal repayIn3DayTotalAmt = BigDecimal.ZERO;
//                            repayIn3DayIouList.stream().forEach(p -> repayIn3DayTotalAmt.add(p.getLoanPrincipal()).add(p.getServiceFee()).add(p.getLoanInterest())
//                                    .subtract(p.getRepaidPrincipal()).subtract(p.getRepaidServiceFee()).subtract(p.getRepaidInterest()));

                    for (int i = 0; i < repayIn3DayIouList.size(); i++) {
                        repayIn3DayTotalAmt = repayIn3DayTotalAmt.add(repayIn3DayIouList.get(i).getLoanPrincipal()).add(repayIn3DayIouList.get(i).getServiceFee()).add(repayIn3DayIouList.get(i).getLoanInterest());
                        repayIn3DayTotalAmt = repayIn3DayTotalAmt.subtract(repayIn3DayIouList.get(i).getRepaidPrincipal().add(repayIn3DayIouList.get(i).getRepaidServiceFee()).add(repayIn3DayIouList.get(i).getRepaidInterest()));
                    }
                    rsp.put("repayIn3DayTotalAmt", repayIn3DayTotalAmt);
                }
            }

        }
        if(rsp.getJSONObject("loanDeferredShow")!=null){
            rsp.getJSONObject("loanDeferredShow").put("overdueAmount", BigDecimalConvertUtil.convert(rsp.getJSONObject("loanDeferredShow").getBigDecimal("overdueAmount")));
        }
        rsp.put("repayIn3DayTotalAmt", BigDecimalConvertUtil.convert(rsp.getBigDecimal("repayIn3DayTotalAmt")));
        rsp.put("overdueTotalAmt", BigDecimalConvertUtil.convert(rsp.getBigDecimal("overdueTotalAmt")));
        return rsp;
    }

    /**
     * 用户首页 - 检查借据是否能延期的显示逻辑
     * @param loanIouList
     * @return
     */
    private Map<String,Object> loanDeferredShow(List<LoanIou> loanIouList){
        Map<String,Object> resultMap = null;
        try{
            //排除掉结清的借据
            List<LoanIou> noEndLoanIouList = loanIouList.stream().filter(obj->obj.getIouStatus()!=1).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(noEndLoanIouList)){
                LoanIou loanIou = noEndLoanIouList.get(0);//前面sql查询根据id倒序，这里取第一条即最近的一笔借据
                //还款到日期 - 有【延期还款到期日】则显示，没有则显示原借据还款到期日
                String repayDate = StringUtils.isNotEmpty(loanIou.getDeferredRepayDate())?loanIou.getDeferredRepayDate():loanIou.getRepayDate();
                resultMap = new HashMap<>();
                resultMap.put("repayDate",DateUtils.formatDate(DateUtils.parseDate(repayDate,DateUtils.YYYY_MM_DD_SLASH),DateUtils.DD_MM_YYYY_SLASH));
                //剩余应还金额
                resultMap.put("overdueAmount",LoanIou.calculationOverdueAmount(loanIou).setScale(1, RoundingMode.HALF_UP));
                //借据状态:0-Normal 1-End 2-Overdue
                resultMap.put("iouStatus",loanIou.getIouStatus());
                //借据号
                resultMap.put("loanSerialNo",loanIou.getLoanSerialNo());
                //是否可以延期
                boolean isApplyDeferred = false;
                List<ProductDeferredInfo> productDeferredInfoList = processForIouDefferredService.getSelectDefferreds(loanIou.getLoanSerialNo());
                if(!CollectionUtils.isEmpty(productDeferredInfoList)){
                    //获取可用的
                    long activeCount = productDeferredInfoList.stream().filter(obj->obj.getMsgIndex()==null || obj.getMsgIndex()<=-1).count();
                    if(activeCount>0L){ //可用的延期产品大于0 则显示延期按钮
                        isApplyDeferred = true;
                    }
                }
                resultMap.put("isApplyDeferred",isApplyDeferred);
                return resultMap;
            }
        }catch (Exception e){
            log.error("借据是否能延期的显示逻辑异常",e);
        }
        return resultMap;
    }

    private JSONObject buildChannelCard(CreditAccount creditAccount) {

        AppUser validInviter = appService.getValidInviter(getAppUser().getRecommendCode());
        if (validInviter == null) {
            return null;
        }
        JSONObject json = new JSONObject();
        json.put("inviterNickname", validInviter.getNickName());
        //渠道额度
        json.put("channelQuota", iSysConfigService.selectConfigByKey("advance_credit"));
        if (creditAccount != null) {
            //渠道额度
            json.put("channelQuota", String.valueOf(creditAccount.getChannelQuota().setScale(2, BigDecimal.ROUND_HALF_UP)));
            //最终额度
            json.put("finalLoan", String.valueOf(creditAccount.getCreditLine().setScale(2, BigDecimal.ROUND_HALF_UP)));
        }
        return json;
    }

    private boolean checkBindCardFlag(String userUUId) {
        CustBankCard custBankCard = new CustBankCard();
        custBankCard.setUserId(userUUId);
        custBankCard.setState(BizConstants.BIZ_STATUS_1);
        List<CustBankCard> custBankCardList = custBankCardService.selectCustBankCardList(custBankCard);
        return !CollectionUtils.isEmpty(custBankCardList);
    }

    private String formatPhone(String phoneNumber) {
        phoneNumber = phoneNumber.replaceAll("-", "").replaceAll(" ", "").replaceAll("\\+", "");
        phoneNumber = phoneNumber.startsWith("0") ? "234" + phoneNumber.substring(1) : (phoneNumber.startsWith("2340") ? phoneNumber.replace("2340", "234") : phoneNumber);
        return phoneNumber;
    }

    //客户通话记录授权
    public JSONObject callList(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String applyNo = dataJson.get("applyNo") == null ? null : dataJson.getString("applyNo");

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(dataJson.get("userId").toString());
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);

        //根据用户获取客户id
        /*CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(user.getUserUuid());
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() < 1) {
            throw new BusinessException(RspEnmu.SYSTEM_EXCEPTION);
        }
        CustomerInfo custInfo = customerInfoList.get(0);
        String custNo = custInfo.getCustNo();*/

        String saveResult = "0";
        //保存通讯录
        String batchNo = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss");
        JSONArray dataJsonArr = dataJson.getJSONArray("callList");
        for (int i = 0; i < dataJsonArr.size(); i++) {
            JSONObject tempObject = dataJsonArr.getJSONObject(i);
            if (null == tempObject.get("phone") || StringUtils.isBlank(tempObject.get("phone").toString())) {
                continue;
            } else {
                ApplyCallLog applyCallLog = new ApplyCallLog();
                applyCallLog.setCustNo(user.getUserUuid());
                applyCallLog.setBatchNo(batchNo);
                applyCallLog.setApplyNo(applyNo);
                applyCallLog.setState(UserConstants.NORMAL);
                applyCallLog.setCreateTime(new Date());
                if (null == tempObject.get("callName") || StringUtils.isBlank(tempObject.get("callName").toString())) {
                    applyCallLog.setCallName(tempObject.get("phone").toString());
                } else {
                    applyCallLog.setCallName(tempObject.get("callName").toString());
                }
                applyCallLog.setPhone(tempObject.get("phone").toString());
                if (null != tempObject.get("countryCode") || StringUtils.isNotBlank(tempObject.get("countryCode").toString())) {
                    applyCallLog.setCountryCode(tempObject.get("countryCode").toString());
                }
                if (null != tempObject.get("callTime") || StringUtils.isNotBlank(tempObject.get("callTime").toString())) {
                    applyCallLog.setCallTime(tempObject.get("callTime").toString());
                }
                if (null != tempObject.get("actionType") || StringUtils.isNotBlank(tempObject.get("actionType").toString())) {
                    applyCallLog.setActionType(tempObject.get("actionType").toString());
                }
                if (null != tempObject.get("callStatus") || StringUtils.isNotBlank(tempObject.get("callStatus").toString())) {
                    applyCallLog.setCallStatus(tempObject.get("callStatus").toString());
                }
                if (null != tempObject.get("callDuration") || StringUtils.isNotBlank(tempObject.get("callDuration").toString())) {
                    applyCallLog.setCallDuration(tempObject.getInteger("callDuration"));
                }
                applyCallLogService.insertApplyCallLog(applyCallLog);
                saveResult = "1";
            }
        }

        rsp.put("result", saveResult);
        return rsp;
    }

    //客户短信记录授权
    public JSONObject smsList(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String applyNo = dataJson.get("applyNo") == null ? null : dataJson.getString("applyNo");

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(dataJson.get("userId").toString());
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);

        //根据用户获取客户id
        /*CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(user.getUserUuid());
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() < 1) {
            throw new BusinessException(RspEnmu.SYSTEM_EXCEPTION);
        }
        CustomerInfo custInfo = customerInfoList.get(0);
        String custNo = custInfo.getCustNo();*/

        String saveResult = "0";
        //保存通讯录
        String batchNo = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss");
        JSONArray dataJsonArr = dataJson.getJSONArray("smsList");
        for (int i = 0; i < dataJsonArr.size(); i++) {
            JSONObject tempObject = dataJsonArr.getJSONObject(i);
            if (null == tempObject.get("phone") || StringUtils.isBlank(tempObject.get("phone").toString())) {
                continue;
            } else {
                ApplySms applySms = new ApplySms();
                applySms.setCustNo(user.getUserUuid());
                applySms.setBatchNo(batchNo);
                applySms.setApplyNo(applyNo);
                applySms.setState(UserConstants.NORMAL);
                applySms.setCreateTime(new Date());
                if (null == tempObject.get("contactsName") || StringUtils.isBlank(tempObject.get("contactsName").toString())) {
                    applySms.setContactsName(tempObject.get("phone").toString());
                } else {
                    applySms.setContactsName(tempObject.get("contactsName").toString());
                }
                applySms.setPhone(tempObject.get("phone").toString());
                if (null != tempObject.get("countryCode") || StringUtils.isNotBlank(tempObject.get("countryCode").toString())) {
                    applySms.setCountryCode(tempObject.get("countryCode").toString());
                }
                if (null != tempObject.get("smsTime") || StringUtils.isNotBlank(tempObject.get("smsTime").toString())) {
                    applySms.setSmsTime(tempObject.get("smsTime").toString());
                }
                if (null != tempObject.get("actionType") || StringUtils.isNotBlank(tempObject.get("actionType").toString())) {
                    applySms.setActionType(tempObject.get("actionType").toString());
                }
                if (null != tempObject.get("smsStatus") || StringUtils.isNotBlank(tempObject.get("smsStatus").toString())) {
                    applySms.setSmsStatus(tempObject.get("smsStatus").toString());
                }
                if (null != tempObject.get("smsContent") || StringUtils.isNotBlank(tempObject.get("smsContent").toString())) {
                    applySms.setSmsContent(tempObject.getString("smsContent"));
                }
                applySmsService.insertApplySms(applySms);
                saveResult = "1";
            }
        }

        rsp.put("result", saveResult);
        return rsp;
    }


    public JSONObject getTranPasswordStatus(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String userId = dataJson.get("userId").toString();

        boolean tokenResult = this.gethasLoginResult(userId);
        //登录标记
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(userId);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);
        //状态检查
        if (!UserConstants.NORMAL.equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        CustTransactionSetting query = new CustTransactionSetting();
        query.setUserId(user.getUserUuid());
        query.setState(UserConstants.NORMAL);
        List<CustTransactionSetting> settingList = custTransactionSettingService.selectCustTransactionSettingList(query);
        if (settingList.size() > 0) {
            rsp.put("result", "1");
        } else {
            rsp.put("result", "0");
        }

        return rsp;
    }

    public JSONObject setTransactionPassword(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String password = dataJson.get("password").toString();
        String userId = dataJson.get("userId").toString();

        boolean tokenResult = this.gethasLoginResult(userId);
        //登录标记
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(userId);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);
        //状态检查
        if (!UserConstants.NORMAL.equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        String passWord = bCryptPasswordEncoder.encode(password);
        CustTransactionSetting query = new CustTransactionSetting();
        query.setUserId(user.getUserUuid());
        query.setState(UserConstants.NORMAL);
        List<CustTransactionSetting> settingList = custTransactionSettingService.selectCustTransactionSettingList(query);
        if (settingList.size() > 0) {
            CustTransactionSetting custTransactionSetting = settingList.get(0);
            custTransactionSetting.setPassword(passWord);
            custTransactionSetting.setState(UserConstants.NORMAL);
            custTransactionSettingService.updateCustTransactionSetting(custTransactionSetting);
        } else {
            CustTransactionSetting custTransactionSetting = new CustTransactionSetting();
            custTransactionSetting.setPassword(passWord);
            custTransactionSetting.setState(UserConstants.NORMAL);
            custTransactionSetting.setUserId(user.getUserUuid());
            custTransactionSettingService.insertCustTransactionSetting(custTransactionSetting);
        }

        rsp.put("result", "1");
        return rsp;
    }

    public JSONObject checkTranPassword(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String password = dataJson.get("password").toString();
        String userId = dataJson.get("userId").toString();

        boolean tokenResult = this.gethasLoginResult(userId);
        //登录标记
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(userId);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);
        //状态检查
        if (!UserConstants.NORMAL.equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        CustTransactionSetting query = new CustTransactionSetting();
        query.setUserId(user.getUserUuid());
        query.setState(UserConstants.NORMAL);
        List<CustTransactionSetting> settingList = custTransactionSettingService.selectCustTransactionSettingList(query);
        if (settingList.size() > 0) {
            CustTransactionSetting CustTransactionSetting = settingList.get(0);

            if (StringUtils.isBlank(CustTransactionSetting.getPassword())) {
                throw new BusinessException(RspEnmu.NOT_SET_TRADE_PASSWORD);
            }

            //判断密码是否正确
            if (!bCryptPasswordEncoder.matches(password, CustTransactionSetting.getPassword())) {
                throw new BusinessException(RspEnmu.T_PASSWORD_ERR);
            }

            rsp.put("result", "1");
        } else {
            throw new BusinessException(RspEnmu.NOT_SET_TRADE_PASSWORD);
        }
        return rsp;
    }

    public JSONObject tranPasswordSmsCode(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String bvnAccount = dataJson.get("bvnAccount").toString();
        String userId = dataJson.get("userId").toString();

        boolean tokenResult = this.gethasLoginResult(userId);
        //登录标记
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(userId);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);
        //状态检查
        if (!UserConstants.NORMAL.equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        //获取实名认证信息
        RealNameAuth realNameQuery = new RealNameAuth();
        realNameQuery.setUserId(user.getUserUuid());
        realNameQuery.setState(UserConstants.BUSINESS_NORMAL);
        List<RealNameAuth> realNameList = realNameAuthService.selectRealNameAuthList(realNameQuery);
        if (realNameList.size() < 1) {
            throw new BusinessException(RspEnmu.NOT_VERIFY_REAL_NAME);
        } else {
            RealNameAuth realNameAuth = realNameList.get(0);
            if (!bvnAccount.equals(realNameAuth.getBvnAccount())) {
                throw new BusinessException(RspEnmu.BVN_VERIFY_REJECT);
            }

            if (StringUtils.isBlank(realNameAuth.getPhoneNumber())) {
                throw new BusinessException(RspEnmu.SYSTEM_EXCEPTION);
            }

            SmsSendReq smsReq = new SmsSendReq();
            smsReq.setSmsType("reset_trans_pwd");
            smsReq.setPhoneNumber(realNameAuth.getPhoneNumber());
            SmsSendData smsData = smsService.sendVerifyCode(smsReq, true);
            rsp.put("uuid", smsData.getUuid());
        }

        return rsp;
    }

    public JSONObject forgetTranPassword(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String bvnAccount = dataJson.get("bvnAccount").toString();
        String userId = dataJson.get("userId").toString();
        String verifyCode = dataJson.get("verifyCode").toString();
        String uuid = dataJson.get("uuid").toString();

        boolean tokenResult = this.gethasLoginResult(userId);
        //登录标记
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(userId);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);
        //状态检查
        if (!"0".equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        //获取实名认证信息
        RealNameAuth realNameQuery = new RealNameAuth();
        realNameQuery.setUserId(user.getUserUuid());
        realNameQuery.setState(UserConstants.BUSINESS_NORMAL);
        List<RealNameAuth> realNameList = realNameAuthService.selectRealNameAuthList(realNameQuery);
        if (realNameList.size() < 1) {
            throw new BusinessException(RspEnmu.NOT_VERIFY_REAL_NAME);
        } else {
            RealNameAuth realNameAuth = realNameList.get(0);
            if (!bvnAccount.equals(realNameAuth.getBvnAccount())) {
                throw new BusinessException(RspEnmu.BVN_VERIFY_REJECT);
            }

            smsService.verifySmsCode(SmsSendVo.builder().countryCode("+234").phoneNumber(realNameAuth.getPhoneNumber())
                    .verifyCode(verifyCode).smsType("reset_trans_pwd").uuid(uuid).build());

            rsp.put("result", "1");
        }

        return rsp;
    }

    //更新客户信息过期字段
    public JSONObject updateExpireCustInfo(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();
        log.info("更新客户信息过期字段的参数 :" + dataJson);
        JSONArray updateFieldArray = new JSONArray();
        // 遍历key value
        Iterator<String> keys = dataJson.keySet().iterator();
        while (keys.hasNext()) {
            JSONObject json = new JSONObject();
            String key = keys.next();
            String value = dataJson.getString(key);
            json.put(key, value);
            updateFieldArray.add(json);
        }
        if (updateFieldArray.size() < 1) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }
        //是否登录成功
        String userId = getUserId();
        boolean tokenResult = this.gethasLoginResult(userId);
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //根据用户获取客户id
        CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(userId);
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() < 1) {
            throw new BusinessException(RspEnmu.CUST_IS_NULL_NEED_REALNAME_AUTH);
        }
        CustomerInfo custInfo = customerInfoList.get(0);
        Date nowTime = new Date();
        // 更新用户信息，添加变更记录
        List<CustBaseChangeLog> updateList = new ArrayList<CustBaseChangeLog>();
        for (int i = 0; i < updateFieldArray.size(); i++) {
            JSONObject fieldObject = updateFieldArray.getJSONObject(i);
            Iterator<String> moreKeys = fieldObject.keySet().iterator();
            while (moreKeys.hasNext()) {
                String key = moreKeys.next();
                String value = fieldObject.getString(key);
                if (StringUtils.isNotEmpty(key) && StringUtils.isNotBlank(value)) {
                    CustBaseChangeLog custBaseChangeLog = new CustBaseChangeLog();
                    custBaseChangeLog.setCustNo(custInfo.getUserId());
                    custBaseChangeLog.setInfoType(key);
                    custBaseChangeLog.setChangeAfter(value);
                    custBaseChangeLog.setState(UserConstants.BUSINESS_NORMAL);
                    custBaseChangeLog.setCreateTime(nowTime);
                    custBaseChangeLog.setUpdateTime(nowTime);
                    switch (key) {
                        case UpdateRelationConstants.RELATION:
                            custBaseChangeLog.setChangeBefore(custInfo.getRelation());
                            custInfo.setRelation(value);
                            custInfo.setRelateUpdated(nowTime);
                            break;
                        case UpdateRelationConstants.RELATENAME:
                            custBaseChangeLog.setChangeBefore(custInfo.getRelateName());
                            custInfo.setRelateName(value);
                            custInfo.setRelateUpdated(nowTime);
                            break;
                        case UpdateRelationConstants.RELATEPHONE:
                            custBaseChangeLog.setChangeBefore(custInfo.getRelatePhone());
                            custInfo.setRelatePhone(value);
                            custInfo.setRelateUpdated(nowTime);
                            break;
                        /*case UpdateRelationBizConstants.RELATION2 :
                            custBaseChangeLog.setChangeBefore(custInfo.getRelation2());
                            custInfo.setRelation2(value);
                            custInfo.setRelateUpdated(nowTime);
                            break;
                        case UpdateRelationBizConstants.RELATENAME2 :
                            custBaseChangeLog.setChangeBefore(custInfo.getRelateName2());
                            custInfo.setRelateName2(value);
                            custInfo.setRelateUpdated(nowTime);
                            break;
                        case UpdateRelationBizConstants.RELATEPHONE2 :
                            custBaseChangeLog.setChangeBefore(custInfo.getRelatePhone2());
                            custInfo.setRelatePhone2(value);
                            custInfo.setRelateUpdated(nowTime);
                            break;*/
                        default:
                            throw new BusinessException(RspEnmu.UPDATE_RELATION_PARAM);
                    }
                    updateList.add(custBaseChangeLog);
                }
            }


        }
        log.info("更新用户联系人信息，增加更改日志");
        // 更新用户联系人信息
        customerInfoService.updateCustomerInfo(custInfo);
        //批量增加更改日志
        custBaseChangeLogService.saveBatch(updateList);
        rsp.put("result", "1");
        return rsp;
    }

    //获取客户信息过期字段
    public JSONObject getCustInfoExpire(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();
        JSONArray fieldList = new JSONArray();

//        String userUUId = null;
//        if (null != dataJson.get("userId") || StringUtils.isNotBlank(dataJson.get("userId").toString())) {
//            userUUId = dataJson.get("userId").toString();
//        }
//
//        //是否登录成功
//        boolean tokenResult = this.gethasLoginResult(userUUId);
//        if (!tokenResult) {
//            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
//        }

        //根据用户获取客户id
        CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(getUserId());
        // 查询出来用户信息，做更新使用
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() > 0) {
            //throw new BusinessException(RspEnmu.CUST_IS_NULL_NEED_REALNAME_AUTH);
            CustomerInfo custInfo = customerInfoList.get(0);

        	/*String custNo = custInfo.getCustNo();
             * CreditApply apply = new CreditApply();
            apply.setCustNo(custNo);
            apply.setApplyStatus(BizConstants.APPLY_STATUS_1_PASSED);
            apply.setState(UserConstants.BUSINESS_NORMAL);
            List<CreditApply> creditApplys = creditApplyService.selectCreditApplyList(apply);
            if (creditApplys.size() < 1) {
                throw new BusinessException(RspEnmu.NOT_MATCH_PASS_APPLY);
            }*/

            Date nowTime = new Date();
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(nowTime);
            Date expireDate = calendar.getTime();

            //学历
           /* Date updateTime = custInfo.getDegreeUpdated();//学历1年
            if (null != updateTime) {
                calendar.setTime(updateTime);
                calendar.add(calendar.YEAR, 1); //增加一年
                if (expireDate.before(nowTime)) {//逾期
                    fieldList.add("degree");
                }
            }*/
            //职业
            /*updateTime = custInfo.getOccupationUpdated();//职业6个月
            if (null != updateTime) {
                calendar.setTime(updateTime);
                calendar.add(calendar.MONTH, 6); //增加6月
                expireDate = calendar.getTime();
                if (expireDate.before(nowTime)) {//逾期
                    fieldList.add("occupation");
                }
            }*/
            //联系人，如果联系人更新时间加上六个月在当前时间之前   联系人过期
            Date updateTime = custInfo.getRelateUpdated();//联系人6个月
            if (null != updateTime) {
                calendar.setTime(updateTime);
                calendar.add(calendar.MONTH, 6); //增加6月
                expireDate = calendar.getTime();
                if (expireDate.before(nowTime)) {//逾期
                    fieldList.add("relation");
                    fieldList.add("relateName");
                    fieldList.add("relatePhone");
                    /*fieldList.add("relation2");
                    fieldList.add("relateName2");
                    fieldList.add("relatePhone2");*/
                }
            }
        }
        // 把过期字段和过期字段的数量返回给前端
        rsp.put("fieldList", fieldList);
        rsp.put("fieldCount", fieldList.size());
        return rsp;
    }

    //获取借据list
    public JSONObject getLoanList(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();
        JSONArray loanList = new JSONArray();

        String userUUId = getUserId();

        //根据用户获取客户id
        CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(userUUId);
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() < 1) {
            //throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
            rsp.put("amountToBeReturned", "0");
            rsp.put("loanList", loanList);
            return rsp;
        }
        CustomerInfo custInfo = customerInfoList.get(0);
        String custNo = custInfo.getCustNo();

        CreditAccount creditAccount = new CreditAccount();
        creditAccount.setCustNo(custNo);
        //creditAccount.setOnLoan("1");//在贷
        creditAccount.setState(UserConstants.BUSINESS_NORMAL);
        List<CreditAccount> selectCreditAccountList = creditAccountService.selectCreditAccountList(creditAccount);
        if (selectCreditAccountList.size() < 1) {
            //throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
            rsp.put("amountToBeReturned", "0");
            rsp.put("loanList", loanList);
            rsp.put("recordCount", "0");
            return rsp;
        }

        //总待还计算
        creditAccount = selectCreditAccountList.get(0);
        if ("1".equals(creditAccount.getOnLoan())) {//在贷
            BigDecimal loanPrincipal = creditAccount.getLoanPrincipal();//放款本金
            BigDecimal amountToBeReturned = loanPrincipal.subtract(creditAccount.getRepaidPrincipal());//减去已还本金

            amountToBeReturned = amountToBeReturned.add(creditAccount.getServiceFee());//加上服务费
            amountToBeReturned = amountToBeReturned.subtract(creditAccount.getRepaidServiceFee());//减去以还服务费

            amountToBeReturned = amountToBeReturned.add(creditAccount.getLoanInterest());//加上利息
            amountToBeReturned = amountToBeReturned.subtract(creditAccount.getRepaidInterest());//减去以还利息

            amountToBeReturned = amountToBeReturned.add(creditAccount.getLateFee());//加上利息
            amountToBeReturned = amountToBeReturned.subtract(creditAccount.getRepaidLateFee());//减去以还利息
            rsp.put("amountToBeReturned", amountToBeReturned);
        } else {
            rsp.put("amountToBeReturned", "0");
        }

        String status = null;
        if (Func.isNotEmpty(dataJson.get("loanStatus"))) {
            status = dataJson.getString("loanStatus");
        }
        RealNameAuth realNameQuery = new RealNameAuth();
        realNameQuery.setUserId(userUUId);
        // realNameQuery.setState(UserConstants.BUSINESS_NORMAL);
        List<RealNameAuth> realNameList = realNameAuthService.selectRealNameAuthList(realNameQuery);
        if (realNameList.size() < 1) {
            throw new BusinessException(RspEnmu.CUST_IS_NULL_NEED_REALNAME_AUTH);
        }
        //获取借据列表
        List<LoanInfo> loanInfoList = loanInfoService.getLoanInfoListByCustNo(custNo, status);
        if (loanInfoList.size() > 0) {
            String custName = realNameList.get(0).getFirstName() + "." + realNameList.get(0).getMiddleName()
                    + "." + realNameList.get(0).getLastName();
            for (LoanInfo p : loanInfoList) {
                JSONObject info = new JSONObject();
                info.put("loanNo", p.getLoanSerialNo());
                // 如果为延期借据，还款日取延期借据还款日
                if (Objects.nonNull(p.getIsDeferred()) && 1 == p.getIsDeferred()) {
                    info.put("repayDate", p.getDeferredRepayDate());
                } else {
                    info.put("repayDate", Func.isNotEmpty(p.getIouRepayDate()) ? p.getIouRepayDate() : p.getOrderRepayDate());
                }
                info.put("custName", custName);
                info.put("createTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, p.getCreateTime()));
                info.put("productName", p.getProductName());
                long loanAmt = p.getLoanAmt().setScale(2, BigDecimal.ROUND_HALF_UP).longValue();
                info.put("loanAmt", loanAmt);
                if (null != p.getLoanStatus()) {
                    info.put("payStatus", InitDataConfig.LOAN_ORDER_STATUS_MAP.get(p.getLoanStatus().toString()));
                }
                if (null != p.getIouStatus()) {
                    log.info("p.getIouStatus():{}",p.getIouStatus());
                    Map<String, Object> minRepay = processForIouDefferredService.getMinRepayBySerialNo(p.getLoanSerialNo());
                    if (Func.isNotEmpty(minRepay)) {
                        info.put("minRepay", minRepay.get("minRepay"));
                    }
                    info.put("iouStatus", p.getIouStatus());
//                    info.put("loanStatus", InitDataConfig.LOAN_IOU_STATUS_MAP.get(p.getIouStatus().toString()));
                    if (1 != p.getIouStatus()) {
                        info.put("showRepaidBtn", "1");
                    } else {
                        info.put("showRepaidBtn", "0");
                    }
                } else {
                    info.put("loanStatus", p.getLoanStatus());
                    info.put("showRepaidBtn", "0");
                }
                loanList.add(info);
            }
        }
        List<JSONObject> loanInfoListSort = loanInfoService.loanInfoListSort(loanList.toJavaList(JSONObject.class));
        if(!CollectionUtils.isEmpty(loanInfoListSort)){ //转换金额格式
            loanInfoListSort.forEach(obj->{
                if(StringUtils.isNotEmpty(obj.getString("minRepay"))){
                    obj.put("minRepay",BigDecimalConvertUtil.convert(obj.getBigDecimal("minRepay")));
                }
            });
        }
        rsp.put("loanList", loanInfoListSort);
        rsp.put("recordCount", loanList.size());
        return rsp;
    }

    //获取借据list
    public JSONObject getLoanInfo(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

//        String userUUId = null;
//        if (null != dataJson.get("userId") || StringUtils.isNotBlank(dataJson.get("userId").toString())) {
//            userUUId = dataJson.get("userId").toString();
//        }
//        String serialNo = null;
//        if (null != dataJson.get("loanNo") || StringUtils.isNotBlank(dataJson.get("loanNo").toString())) {
//            serialNo = dataJson.get("loanNo").toString();
//        }

        //是否登录成功
        /*boolean tokenResult = this.gethasLoginResult(userUUId);
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }*/

        String userId = getUserId();
        String serialNo = dataJson.get("loanNo").toString();

        //根据用户获取客户id
        CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(userId);
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() < 1) {
            throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
        }
        CustomerInfo custInfo = customerInfoList.get(0);
        String custNo = custInfo.getCustNo();

        //获取借据详情
        LoanInfo loanInfo = loanInfoService.getLoanInfoListBySerialNo(custNo, serialNo);
        if (null != loanInfo) {
            RealNameAuth realNameQuery = new RealNameAuth();
            realNameQuery.setUserId(userId);
            realNameQuery.setState(UserConstants.BUSINESS_NORMAL);
            List<RealNameAuth> realNameList = realNameAuthService.selectRealNameAuthList(realNameQuery);
            if (realNameList.size() < 1) {
                throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
            }

            String custName = "";
            if (Func.isEmpty(realNameList.get(0).getMiddleName())) {
                custName = realNameList.get(0).getFirstName() + "." + realNameList.get(0).getLastName();
            } else {
                custName = realNameList.get(0).getFirstName() + "." + realNameList.get(0).getMiddleName() + "." + realNameList.get(0).getLastName();
            }
            rsp.put("loanNo", loanInfo.getLoanSerialNo());
            rsp.put("custName", custName);
            rsp.put("createTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, loanInfo.getCreateTime()));
            rsp.put("productName", loanInfo.getProductName());

            if (loanInfo.getRepaidPrincipal() == null) {
                loanInfo.setRepaidPrincipal(BigDecimal.ZERO);
            }

            long loanPrincipal1 = loanInfo.getLoanPrincipal().setScale(2, BigDecimal.ROUND_HALF_UP).longValue();
            rsp.put("loanAmt", loanInfo.getLoanPrincipal().setScale(2, BigDecimal.ROUND_HALF_UP).longValue());

            rsp.put("loanPrincipal", loanPrincipal1);

            rsp.put("periodNum", loanInfo.getPeriodNum());
            rsp.put("unit", loanInfo.getUnit());

            rsp.put("repayDate", Func.isEmpty(loanInfo.getIouRepayDate()) ? loanInfo.getOrderRepayDate() : loanInfo.getIouRepayDate());
            rsp.put("deferredRepayDate", loanInfo.getDeferredRepayDate());
            if (loanInfo.getRepaidInterest() == null) {
                loanInfo.setRepaidInterest(BigDecimal.ZERO);
            }
            rsp.put("interestAmt", InitDataConfig.currency.format(loanInfo.getLoanInterest().setScale(2, BigDecimal.ROUND_HALF_UP)));

            if (loanInfo.getRepaidServiceFee() == null) {
                loanInfo.setRepaidServiceFee(BigDecimal.ZERO);
            }
            rsp.put("serviceFee", InitDataConfig.currency.format(loanInfo.getServiceFee().setScale(2, BigDecimal.ROUND_HALF_UP)));

            BigDecimal loanPrincipal = loanInfo.getLoanPrincipal();//放款本金
            // minRepay 最低还款
            Map<String, Object> minRepay = processForIouDefferredService.getMinRepayBySerialNo(loanInfo.getLoanSerialNo());
            if (Func.isNotEmpty(minRepay)) {
                rsp.put("minRepay", minRepay.get("minRepay"));
                // 返回延期产品金融包的产品id，用户勾选默认支付选项，deferredId获取不到时，自动勾选repayAll
                rsp.put("deferredId", minRepay.get("deferredId"));
            }
            BigDecimal amountToBeReturned = new BigDecimal("0.00");
            BigDecimal repaidAmt = new BigDecimal("0.00");
            BigDecimal lateFee = new BigDecimal("0.00");
            if (null != loanPrincipal) {

                amountToBeReturned = loanPrincipal.subtract(loanInfo.getRepaidPrincipal());//减去已还本金

                amountToBeReturned = amountToBeReturned.add(loanInfo.getServiceFee());//加上服务费
                amountToBeReturned = amountToBeReturned.subtract(loanInfo.getRepaidServiceFee());//减去以还服务费

                amountToBeReturned = amountToBeReturned.add(loanInfo.getLoanInterest());//加上利息
                amountToBeReturned = amountToBeReturned.subtract(loanInfo.getRepaidInterest());//减去以还利息

                if (loanInfo.getLateFee() == null) {
                    loanInfo.setLateFee(BigDecimal.ZERO);
                }

                if (loanInfo.getRepaidLateFee() == null) {
                    loanInfo.setRepaidLateFee(BigDecimal.ZERO);
                }

                amountToBeReturned = amountToBeReturned.add(loanInfo.getLateFee());//加上滞纳金
                amountToBeReturned = amountToBeReturned.subtract(loanInfo.getRepaidLateFee()).subtract(loanInfo.getFeeRemissionAmt()==null?BigDecimal.ZERO:loanInfo.getFeeRemissionAmt());//减去以滞纳金

                if (loanInfo.getRepaidLateFee() == null) {
                    loanInfo.setRepaidServiceFee(BigDecimal.ZERO);
                }

                repaidAmt = loanInfo.getLoanPrincipal().add(loanInfo.getServiceFee());//加上服务费
                repaidAmt = repaidAmt.add(loanInfo.getLoanInterest());
                repaidAmt = repaidAmt.add(loanInfo.getLateFee()).subtract(loanInfo.getFeeRemissionAmt()==null?BigDecimal.ZERO:loanInfo.getFeeRemissionAmt());
                if(null!=loanInfo.getIsDeferred() && 1==loanInfo.getIsDeferred()){
                    // 存在延期，获取延期的已经还的 查询所有循环
                    List<LoanIouDeferred> loanIouDeferredList =  loanIouDeferredMapper.selectList(new QueryWrapper<LoanIouDeferred>().select("service_fee", "interest_fee", "repaid_service_fee", "repaid_interest_fee").eq("loan_serial_no", loanInfo.getLoanSerialNo()));
                    if(!CollectionUtils.isEmpty(loanIouDeferredList)){
                        for (int i = 0; i < loanIouDeferredList.size(); i++) {
                            LoanIouDeferred loanIouDeferred = loanIouDeferredList.get(i);
                            repaidAmt = repaidAmt.add(loanIouDeferred.getServiceFee()).add(loanIouDeferred.getInterestFee());

                            amountToBeReturned = amountToBeReturned.add(loanIouDeferred.getServiceFee()).add(loanIouDeferred.getInterestFee());
                            amountToBeReturned = amountToBeReturned.subtract(loanIouDeferred.getRepaidServiceFee()).subtract(loanIouDeferred.getRepaidInterestFee());

                        }
                    }

                }

                if (null != loanInfo.getIouStatus()) {
                    lateFee = loanInfo.getLateFee();
                }
            }
            QueryWrapper<CustAndonLog> custAndonLogWrapper = new QueryWrapper<>();
            custAndonLogWrapper.eq("relation_sn", loanInfo.getLoanSerialNo());
            custAndonLogWrapper.eq("cust_no", loanInfo.getCustNo());
            custAndonLogWrapper.eq("type", BizConstants.ANDON_TYPE_LOAN);
            CustAndonLog custAndonLog = iCustAndonLogService.getOne(custAndonLogWrapper);
            if (custAndonLog == null) {
                double dateDiff = DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_SECOND, new Date(), loanInfo.getCreateTime());
                rsp.put("andonSecond", new BigDecimal((60 * 5 - dateDiff) * 1000 < 0 ? 0 : (60 * 5 - dateDiff) * 1000).intValue());
            } else {
                rsp.put("andonSecond", -1);
            }

            //amountToBeReturned = amountToBeReturned.subtract(loanInfo.getFeeRemissionAmt());//减去减免金
            rsp.put("needRepaidAmt", InitDataConfig.currency.format(amountToBeReturned.setScale(0, BigDecimal.ROUND_UP)));
            rsp.put("hasRepaidAmt", InitDataConfig.currency.format(repaidAmt.setScale(2, BigDecimal.ROUND_HALF_UP)));
            if (lateFee.compareTo(BigDecimal.ZERO) == 1) {//大于0
                if (loanInfo.getRepaidLateFee() == null) {
                    loanInfo.setRepaidLateFee(BigDecimal.ZERO);
                }
                if (loanInfo.getFeeRemissionAmt() == null) {
                    loanInfo.setFeeRemissionAmt(BigDecimal.ZERO);
                }
                lateFee = lateFee.subtract(loanInfo.getRepaidLateFee()).subtract(loanInfo.getFeeRemissionAmt());
                rsp.put("lateFee", InitDataConfig.currency.format(lateFee.setScale(2, BigDecimal.ROUND_HALF_UP)));
            }

            if (null != loanInfo.getIouStatus()) {
//                rsp.put("loanStatus", InitDataConfig.LOAN_IOU_STATUS_MAP.get(loanInfo.getIouStatus().toString()));
                rsp.put("iouStatus", loanInfo.getIouStatus());
                if (LoanIou.LOAN_IOU_STATUS_SETTLE != loanInfo.getIouStatus()) {
                    rsp.put("showRepaidBtn", "1");
                    // 延期费用：有延期借据，并且该借据未结清时，展示的金额为0；  该笔借据已结清的话，展示的是该借据买的所有延期包总费用之和
                    if (Objects.nonNull(loanInfo.getIsDeferred()) && 1 == loanInfo.getIsDeferred()) {
                        rsp.put("extensionFree", InitDataConfig.currency.format(BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_UP)));
                    }
                } else {
                    rsp.put("showRepaidBtn", "0");
                    // 结清计算该借据买的所有延期包总费用之和
                    String buyDeferredAmount = getBuyDeferredAmount(loanInfo);
                    if (Objects.nonNull(buyDeferredAmount)) {
                        rsp.put("extensionFree", buyDeferredAmount);
                    }
                }
            } else {
                if (null != loanInfo.getLoanStatus()) {
                    rsp.put("payStatus", InitDataConfig.LOAN_ORDER_STATUS_MAP.get(loanInfo.getLoanStatus().toString()));
                    rsp.put("loanStatus", loanInfo.getLoanStatus());
                }
                rsp.put("showRepaidBtn", "0");
            }

            rsp.put("accountNumber", loanInfo.getAccountNumber());
            ExtIdentityResult extIdentityResult = new ExtIdentityResult();
            extIdentityResult.setAccountNumber(loanInfo.getAccountNumber());
            BankCode bankList = loanInfoService.getBanckInfoByAccountNumber(loanInfo.getAccountNumber());
            rsp.put("bankName", bankList.getPaystackBankName());
            // wqg doCalCustReduce
            // 查询减免费用LoanIou进行查询 reduceAmont
            getReduceAmont(rsp, loanInfo);
        } else {
            throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
        }
        rsp.put("needRepaidAmt",BigDecimalConvertUtil.convert(rsp.getBigDecimal("needRepaidAmt")));
        rsp.put("minRepay",BigDecimalConvertUtil.convert(rsp.getBigDecimal("minRepay")));
        return rsp;
    }


    /**
     * 根据借据号查询已购延期金融包所花费用
     * @param loanInfo
     * @return
     */
    private String getBuyDeferredAmount(LoanInfo loanInfo){
        if (Objects.isNull(loanInfo.getIsDeferred()) || 1 != loanInfo.getIsDeferred()) {
            return null;
        }
        List<LoanIouDeferred> loanIouDeferredList = loanIouDeferredMapper.findNormalDeferredByLoanNo(loanInfo.getLoanSerialNo());
        if (Func.isEmpty(loanIouDeferredList)) {
            return null;
        }
        BigDecimal allMal = BigDecimal.ZERO;
        for (LoanIouDeferred item : loanIouDeferredList) {
            allMal = allMal.add(item.getServiceFee().add(item.getInterestFee()));
        }
        return InitDataConfig.currency.format(allMal.setScale(2, BigDecimal.ROUND_HALF_UP));
    }

    /**
     * 查询减免信息
     *
     * @param rsp
     * @param loanInfo
     */
    public void getReduceAmont(JSONObject rsp, LoanInfo loanInfo) {
        QueryWrapper<LoanIou> wrapper = new QueryWrapper<>();
        wrapper.eq("loan_serial_no", loanInfo.getLoanSerialNo());
        LoanIou loanIou = loanIouService.getOne(wrapper);
        if (null != loanIou) {
            BigDecimal reduceAmont = loanIou.getReduceAmt();
            rsp.put("reduceAmont", reduceAmont == null ? BigDecimal.ZERO : reduceAmont);
        }

    }

    //获取主动还款
    public JSONObject loanRepay(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String userUUId = null;
        if (null != dataJson.get("userId")) {
            userUUId = dataJson.get("userId").toString();
        }
        String serialNo = null;
        if (null != dataJson.get("loanNo")) {
            serialNo = dataJson.get("loanNo").toString();
        }
        String cardId = null;
        if (null != dataJson.get("cardId")) {
            cardId = dataJson.get("cardId").toString();
        }
        String bankCode = null;
        if (null != dataJson.get("bankCode")) {
            bankCode = dataJson.get("bankCode").toString();
        }
        String bankName = null;
        if (null != dataJson.get("bankName")) {
            bankName = dataJson.get("bankName").toString();
        }
        String password = null;
        if (null != dataJson.get("password")) {
            password = dataJson.get("password").toString();
        }

        //登录标记
        boolean tokenResult = this.gethasLoginResult(userUUId);
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //校验用户状态
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(userUUId);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);
        //状态检查
        if (!UserConstants.NORMAL.equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        //验证交易密码
        boolean passwordCheck = false;
        CustTransactionSetting query = new CustTransactionSetting();
        query.setUserId(user.getUserUuid());
        query.setState(UserConstants.NORMAL);
        List<CustTransactionSetting> settingList = custTransactionSettingService.selectCustTransactionSettingList(query);
        if (settingList.size() > 0) {
            CustTransactionSetting CustTransactionSetting = settingList.get(0);
            if (StringUtils.isBlank(CustTransactionSetting.getPassword())) {
                throw new BusinessException(RspEnmu.NOT_SET_TRADE_PASSWORD);
            }
            //判断密码是否正确
            if (bCryptPasswordEncoder.matches(password, CustTransactionSetting.getPassword())) {
                //throw new BusinessException(RspEnmu.USER_PASSWORD_ERR);
                passwordCheck = true;
            } else {
                throw new BusinessException(RspEnmu.T_PASSWORD_ERR);
            }
        } else {
            throw new BusinessException(RspEnmu.NOT_SET_TRADE_PASSWORD);
        }

        if (!passwordCheck) {
            rsp.put("result", "-1");
            return rsp;
        }

        //根据用户获取客户id
        CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(userUUId);
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() < 1) {
            throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
        }
        CustomerInfo custInfo = customerInfoList.get(0);
        String custNo = custInfo.getCustNo();

//        //获取借据详情
//        LoanIou LoanIouQuery = new LoanIou();
//        LoanIouQuery.setCustNo(custNo);
//        LoanIouQuery.setLoanSerialNo(serialNo);
//        LoanIouQuery.setState(UserConstants.BUSINESS_NORMAL);
//        List<LoanIou> loanList = loanIouService.selectLoanIouList(LoanIouQuery);
//
//        //获取账户信息
//        CreditAccount accountQuery = new CreditAccount();
//        accountQuery.setCustNo(custNo);
//        accountQuery.setOnLoan(BizConstants.ACCOUNT_ON_lOAN_STATUS_1);
//        accountQuery.setState(UserConstants.BUSINESS_NORMAL);
//        List<CreditAccount> selectCreditAccountList = creditAccountService.selectCreditAccountList(accountQuery);

        //查询还款银行卡信息
//        CustBankCard bankCard = null;
//        CustBankCard custBankCard = new CustBankCard();
//        custBankCard.setCustNo(custNo);
//        custBankCard.setId(Long.parseLong(cardId));
//        custBankCard.setBankCode(bankCode);
//        custBankCard.setBankName(bankName);
//        custBankCard.setState(UserConstants.BUSINESS_NORMAL);
//        List<CustBankCard> custBankCardList = custBankCardService.selectCustBankCardList(custBankCard);
//        if (custBankCardList.size() == 1) {
//            bankCard = custBankCardList.get(0);
//        }
        CustBankCard bankCard = custBankCardService.selectCustBankCardById(Long.parseLong(cardId));
        //同一张银行卡3小时内只能发起一次主动代扣申请
        String redisKey = BizConstants.LOAN_REPAY_CARD + serialNo;
        Object cacheObject = redisCache.getCacheObject(redisKey);
        if (Func.isNotEmpty(cacheObject)) {
            throw new BusinessException(RspEnmu.REPAYMENT_ORDER_IN_TRANSIT);
        }

        if (null != bankCard) {
            //查询是否有在途的扣款
//                int hasInRepaymentCount = bRepaymentService.getInRepaymentCountByLoan(serialNo);
//                if (hasInRepaymentCount > 0) {//存在在途扣款申请
//                    throw new BusinessException(RspEnmu.REPAYMENT_ORDER_IN_TRANSIT);
//                } else {
//                    boolean result = bLoanInfoService.doRepaymentAction(loanList.get(0), selectCreditAccountList.get(0), bankCard);
//                    if (!result) {
//                        rsp.put("result", "0");
//                    } else {
//                        rsp.put("result", "1");
//                    }
//                }
            String reduceFlag = "noHasReduce";
            BigDecimal reduceAmt = doCalCustReduce.checkCustReduce(serialNo).getReduceAmont();
            if (reduceAmt.compareTo(BigDecimal.ZERO) == 1) {
                reduceFlag = "hasReduce";
            }
            boolean result = bLoanInfoService.doRepaymentAction(serialNo, bankCard, reduceFlag);
            redisCache.setCacheObject(redisKey, bankCard.getCardNumber(), 3, TimeUnit.HOURS);
            if (!result) {
                rsp.put("result", "0");
            } else {
                rsp.put("result", "1");
            }
        } else {
            throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
        }

        return rsp;
    }

    //获取借据合同
    public JSONObject getLoanContract(JSONObject dataJson) {
        JSONObject rsp = new JSONObject();

        String userUUId = null;
        if (null != dataJson.get("userId") || StringUtils.isNotBlank(dataJson.get("userId").toString())) {
            userUUId = dataJson.get("userId").toString();
        }
        String serialNo = null;
        if (null != dataJson.get("loanNo") || StringUtils.isNotBlank(dataJson.get("loanNo").toString())) {
            serialNo = dataJson.get("loanNo").toString();
        }

//        //是否登录成功
//        boolean tokenResult = this.gethasLoginResult(userUUId);
//        if (!tokenResult) {
//            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
//        }

        //根据用户获取客户id
        CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(userUUId);
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() < 1) {
            throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
        }
        CustomerInfo custInfo = customerInfoList.get(0);
        String custNo = custInfo.getCustNo();

        //获取借据申请信息
        LoanOrder loanOrder = new LoanOrder();
        loanOrder.setCustNo(custNo);
        loanOrder.setLoanSerialNo(serialNo);
        loanOrder.setState(UserConstants.BUSINESS_NORMAL);

        String path = "";

        LoanIou loanIou = loanIouService.getLoanIouByLoanSerialNo(serialNo);
        String fileId = "";
        if(null!= loanIou.getIsDeferred() && 1==loanIou.getIsDeferred()){
            // 延期获取子借据的合同
             fileId = loanIouDeferredMapper.getContractNo(serialNo);
        }else{
            List<LoanOrder> selectLoanOrderList = loanOrderService.selectLoanOrderList(loanOrder);
            if (selectLoanOrderList.size() > 0) {
                fileId = selectLoanOrderList.get(0).getContractNo();
            }else {
                throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
            }
        }

        if (StringUtils.isNotBlank(fileId)) {
            SysFiles fileQuery = new SysFiles();
            fileQuery.setMediaId(fileId);
            fileQuery.setStatus(UserConstants.NORMAL);
            List<SysFiles> fileList = sysFilesService.selectSysFilesList(fileQuery);

            //判断是否有AWS地址
            if (fileList.size() == 1) {
                //判断当前版本是否小于2.2.8
                path = fileList.get(0).getAwsS3Url();
                if (VersionUtils.compareVersion(getAppVersion(), "2.2.8") < 0) {
                    path = path.substring(path.indexOf(AMAZONAWS) + AMAZONAWS.length());
                }
            }
        }
        rsp.put("path", path);

        return rsp;
    }

    public JSONObject bvnIsExist(String bvn) {
        if (bvn.length() < 10 || bvn.length() > 12) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }
        RealNameAuth realNameAuth = new RealNameAuth();
        realNameAuth.setBvnAccount(bvn);
        realNameAuth.setState("1");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("res", realNameAuthService.selectRealNameAuthList(realNameAuth).size() == 0);
        return jsonObject;
    }

    //添加日历事件
    public JSONObject addCalendarEvent(JSONObject dataJson) {
        //请求参数校验
        if (Func.hasEmpty(dataJson.get("calendarEvents"), dataJson.get("actionType"), dataJson.get("applyNo"))) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }
        String userId = getUserId();
        JSONObject resjson = new JSONObject();
        JSONArray calendarEvents = dataJson.getJSONArray("calendarEvents");
        String js = JSONObject.toJSONString(calendarEvents);
        List<ApplyCalendar> applyCalendars = JSONObject.parseArray(js, ApplyCalendar.class);
        int res = 0;
        for (ApplyCalendar applyCalendar : applyCalendars) {
            applyCalendar.setActionType(dataJson.get("actionType").toString());
            applyCalendar.setApplyNo(dataJson.get("applyNo").toString());
            applyCalendar.setUserid(userId);
            applyCalendar.setBatchNo(DateFormatUtils.format(new Date(), "yyyyMMddHHmmss"));
            applyCalendar.setCreateDate(new Date());
            try {
                res += applyCalendarService.insertApplyCalendar(applyCalendar);
            } catch (Exception e) {
                log.error("添加日历事件异常，", e);
                // logAsync.saveELog("添加日历事件", e);
            }
        }

        if (res > 0) {
            RulePremiseVo rulePremiseVo = RulePremiseVo.builder().custNo(getCustNo()).type(dataJson.getString("actionType")).serialNo(dataJson.getString("applyNo")).build();
            premiseService.rulePremise(rulePremiseVo, "calendarFlag");
        }

        resjson.put("result", res);
        return resjson;
    }


    //校验授权信息是否在7天有效期 并且 设备指纹一致
    public int applyInfoExpire(String fingerprint) {
        RuleStrategy ruleStrategy = premiseService.getRuleStrategy(RuleStrategy.LOAN);
        return ruleStrategy.applyInfoExpire(fingerprint, getCustNo(), null);
    }

    public JSONObject repaymentTrial(JSONObject params) {

        if (Func.hasEmpty(params.get("productId"), params.get("principal"), params.get("duration"))) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }

        JSONObject result = new JSONObject();
        //获取借据详情
        Long productId = Long.valueOf(params.getString("productId"));
        BigDecimal principal = new BigDecimal(params.getString("principal"));
        BigDecimal duration = new BigDecimal(params.getString("duration"));
        ProductInfo productInfo = productInfoService.selectProductInfoById(productId);
        //利息= 产品利率 * 本金 * 贷期
        BigDecimal interest = productInfo.getInterestRate().multiply(principal).multiply(duration);
        //服务费
        BigDecimal serviceFee = principal.multiply(productInfo.getServiceFee());


        //展示利息
        BigDecimal showInterest = principal.multiply(productInfo.getShowInterestRate()).multiply(duration);
        //展示服务费
        BigDecimal exhibitionService = principal.multiply(productInfo.getShowServiceRate());

        result.put("duration", duration);
        result.put("principal", principal);
        result.put("interest", interest);
        result.put("serviceFee", serviceFee);
        result.put("totalAmount", principal.add(interest).add(serviceFee).setScale(0, BigDecimal.ROUND_UP));
        result.put("showAmount", principal.add(showInterest).add(exhibitionService).setScale(0, BigDecimal.ROUND_UP));
        result.put("repaymentDate", DateUtils.getFewDay(duration.intValue()));
        result.put("showInterest", showInterest.setScale(0, BigDecimal.ROUND_UP));
        result.put("exhibitionService", exhibitionService.setScale(0, BigDecimal.ROUND_UP));
        return result;
    }

    /**
     * 显示原始借据的利息、服务费、罚息
     * 显示extensionFee（延期产品利息+延期服务费）
     *
     * @param params
     * @return
     */
    public JSONObject extensionTrial(JSONObject params) {
        if (Func.hasEmpty(params.get("loanNo"), params.get("deferredId"))) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }
        JSONObject result = new JSONObject();
        String serialNo = params.get("loanNo").toString();
        Long deferredId = params.getLong("deferredId");
        String custNo = getCustNo();
        //获取借据详情
        LoanIou loanIou = getCustomerIouByLoanSerialNo(serialNo, custNo);
        ProductDeferredInfo productDeferredInfo = iProductDeferredInfoService.selectProductDeferredInfoById(deferredId);
        if (Objects.nonNull(loanIou) && Objects.nonNull(productDeferredInfo)) {
            // 原始借据利息、原始借据服务费、原始借据滞纳金
            BigDecimal interestAmt = loanIou.getLoanInterest().subtract(loanIou.getRepaidInterest());
            result.put("interestAmt", InitDataConfig.currency.format(interestAmt.setScale(2, BigDecimal.ROUND_HALF_UP)));
            BigDecimal serviceFee = loanIou.getServiceFee().subtract(loanIou.getRepaidServiceFee());
            result.put("serviceFee", InitDataConfig.currency.format(serviceFee.setScale(2, BigDecimal.ROUND_HALF_UP)));
            BigDecimal lateFee = loanIou.getLateFee().subtract(loanIou.getRepaidLateFee()).subtract(loanIou.getFeeRemissionAmt());
            result.put("lateFee", InitDataConfig.currency.format(lateFee.setScale(2, BigDecimal.ROUND_HALF_UP)));
            // 延期费 = 延期产品利息 + 延期服务费
            BigDecimal toBeRepaid = loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal());
            BigDecimal deferredInterest = toBeRepaid.multiply(productDeferredInfo.getInterestRate()).multiply(new BigDecimal(productDeferredInfo.getNumDeferredDay()));
            BigDecimal deferredServiceFee = toBeRepaid.multiply(productDeferredInfo.getServiceRate());
            BigDecimal extensionFree = deferredInterest.add(deferredServiceFee);
            result.put("deferredInterest", InitDataConfig.currency.format(deferredInterest.setScale(2, BigDecimal.ROUND_HALF_UP)));
            result.put("deferredServiceFee", InitDataConfig.currency.format(deferredServiceFee.setScale(2, BigDecimal.ROUND_HALF_UP)));
            result.put("extensionFree", InitDataConfig.currency.format(extensionFree.setScale(2, BigDecimal.ROUND_HALF_UP)));
            // 选中该延期包后的还款日期、购买该金融包所需支付金额
            String baseRepayDate = Func.isEmpty(loanIou.getDeferredRepayDate()) ? loanIou.getRepayDate() : loanIou.getDeferredRepayDate();
            String repaymentDate = DateUtils.getNewDayV2(baseRepayDate, productDeferredInfo.getNumDeferredDay());
            result.put("repaymentDate", repaymentDate);
            BigDecimal needRepaidAmt = interestAmt.add(serviceFee).add(lateFee).add(extensionFree);
            result.put("needRepaidAmt", InitDataConfig.currency.format(needRepaidAmt.setScale(2, BigDecimal.ROUND_HALF_UP)));
            // 剩余应还本金
            result.put("remainingAmount", InitDataConfig.currency.format(toBeRepaid.setScale(2, BigDecimal.ROUND_HALF_UP)));
        }
        result.put("needRepaidAmt",BigDecimalConvertUtil.convert(result.getBigDecimal("needRepaidAmt")));
        return result;
    }

    /**
     * 还款方式页
     * 1、新增接口校验是否支持延期产品、计算repayall/MinRepay7/Min14还款金额（含本金与期数、是否默认选中））、且默认展示7天（或14天）
     * 2、返回延期产品的激活状态、激活状态码、未生效状态码
     * 3、返回溢缴款钱包可抵扣金额字段 availableOverflow
     */
    public JSONObject repayList(JSONObject params) {
        if (Func.isEmpty(params.get("loanSerialNo"))) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }

        JSONObject rsp = new JSONObject();
        JSONArray loanList = new JSONArray();
        String loanSerialNo = params.getString("loanSerialNo");
        String custNo = getCustNo();
        LoanIou loanIou = getCustomerIouByLoanSerialNo(loanSerialNo, custNo);
        if (null == loanIou) {
            return rsp;
        }
        // 剩余应还本金
        BigDecimal principal = loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal());
        rsp.put("principal", InitDataConfig.currency.format(principal.setScale(2, BigDecimal.ROUND_HALF_UP)));

        buildRepayAllItem(loanList, loanIou);

        List<ProductDeferredInfo> defferredList;
        try {
            defferredList = processForIouDefferredService.getSelectDefferreds(loanSerialNo);
        } catch (ParseException e) {
            log.error("获取延期金融包列表异常，loanSerialNo={}", loanSerialNo, e);
            defferredList = null;
        }
        rsp.put("walletAmount", doRepaymentLastService.getWalletAmount(loanIou.getCustNo()));
        rsp.put("repayList", loanList);
        if (Func.isEmpty(defferredList)) {
            log.info("无可用延期金融包，loanSerialNo={}", loanSerialNo);
            return rsp;
        }

        for (ProductDeferredInfo item : defferredList) {
            JSONObject info = new JSONObject();
            info.put("repayName", MIN_REPAY_NAME);
            info.put("deferredId", item.getId());
            // flase 代表该延期产品可用
            // true + msgIndex等于0 表示xx等级的用户可以使用延期还款，请保持良好的还款记录，提升自己等级，解锁延期还款功能。点击确认（如图4-1），关闭弹框，停留在当前页面；
            // true + msgIndex等于1 弹框提示：请按期还款，保持良好的还款记录，解锁延期还款功能
            // 是否置灰锁
            if (item.isNeedLocked()) {
                // 置灰提示
                info.put("msgIndex", item.getMsgIndex());
            }
            // 单次延期天数
            info.put("numDeferredDay", item.getNumDeferredDay());
            // 选择该延期产品所需交的费用
            BigDecimal minRepay = processForIouDefferredService.getMinPay(loanIou, item);
            info.put("repayAmount", InitDataConfig.currency.format(minRepay.setScale(2, BigDecimal.ROUND_HALF_UP)));
            loanList.add(info);
        }
        if(!CollectionUtils.isEmpty(loanList)){
            for (int i = 0; i < loanList.size(); i++) {
                JSONObject jsonObject = (JSONObject)loanList.get(i);
                jsonObject.put("repayAmount",BigDecimalConvertUtil.convert(jsonObject.getBigDecimal("repayAmount")));
            }
        }
        return rsp;
    }

    /**
     * 列表填充全额还款
     *
     * @param loanList
     * @param loanIou
     */
    private void buildRepayAllItem(JSONArray loanList, LoanIou loanIou) {
        JSONObject repayAll = new JSONObject();
        // 全额支付的时候， productCode 值为null
        repayAll.put("repayName", REPAY_ALL_NAME);
        repayAll.put("deferredId", null);
        BigDecimal totalAmount = getTotalAmount(loanIou);
        repayAll.put("repayAmount", InitDataConfig.currency.format(totalAmount.setScale(2, BigDecimal.ROUND_HALF_UP)));
        loanList.add(repayAll);
    }

    /**
     * 计算全额还款
     * 全额还款金额=罚息+利息+服务费+本金
     *
     * @param loanIou
     */
    private BigDecimal getTotalAmount(LoanIou loanIou) {
        BigDecimal toBeRepaid = loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal());
        BigDecimal interestAmt = loanIou.getLoanInterest().subtract(loanIou.getRepaidInterest());
        BigDecimal serviceFee = loanIou.getServiceFee().subtract(loanIou.getRepaidServiceFee());
        BigDecimal lateFee = loanIou.getLateFee().subtract(loanIou.getRepaidLateFee()).subtract(loanIou.getFeeRemissionAmt());
        return toBeRepaid.add(interestAmt).add(serviceFee).add(lateFee);

    }

    private LoanIou getCustomerIouByLoanSerialNo(String loanSerialNo, String custNo) {
        QueryWrapper<LoanIou> loanIouQueryWrapper = new QueryWrapper<>();
        loanIouQueryWrapper.eq("loan_serial_no", loanSerialNo)
                .eq("cust_no", custNo)
                .eq("state", UserConstants.BUSINESS_NORMAL)
                .last("limit 1");
        LoanIou loanIou = loanIouService.getBaseMapper().selectOne(loanIouQueryWrapper);
        if (Objects.isNull(loanIou)) {
            log.info("getCustomerIouByLoanSerialNo {}:借据不存在", loanSerialNo);
            return null;
        }
        return loanIou;
    }

    /**
     * 新的还款试算，loanSerialNo查询对应的数据
     *
     * @param params
     * @return
     */
    public JSONObject repaymentTrialByloanSerialNo(JSONObject params) {
        if (Func.hasEmpty(params.get("loanSerialNo"))) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }
        JSONObject result = new JSONObject();
        //获取借据详情
        Long productId = Long.valueOf(params.getString("productId"));
        BigDecimal principal = new BigDecimal(params.getString("principal"));
        BigDecimal duration = new BigDecimal(params.getString("duration"));

        ProductInfo productInfo = productInfoService.selectProductInfoById(productId);
        //利息= 产品利率 * 本金 * 贷期
        BigDecimal interest = productInfo.getInterestRate().multiply(principal).multiply(duration);
        //服务费
        BigDecimal serviceFee = principal.multiply(productInfo.getServiceFee());

        result.put("duration", duration);
        result.put("principal", principal);
        result.put("interest", interest);
        result.put("serviceFee", serviceFee);
        result.put("totalAmount", principal.add(interest).add(serviceFee).setScale(0, BigDecimal.ROUND_UP));
        result.put("repaymentDate", DateUtils.getFewDay(duration.intValue()));
        return result;
    }

    public JSONObject accountIsExist(String account, String recommendCode,String linkRecommendCode) {
        if (appUserService.accountIsExist(account)) throw new BusinessException(RspEnmu.USER_EXIST);
        this.inviteCodeValid(account, recommendCode,linkRecommendCode);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("res", true);
        return jsonObject;
    }

    private String inviteCodeValid(String phone, String... inviteCodes) {
        if (inviteCodes.length == 0) return null;

        boolean verify = "1".equals(getDictLabel("biz_switch", "invite_code_verify"));
        for (int i = 0; i < inviteCodes.length; i++) {
            int inviteRelationCount = appUserService.count(new QueryWrapper<AppUser>()
                    .eq("invite_code", inviteCodes[i])
                    .eq("invite_code_status", "1")
                    .eq("state", UserStatusEnum.NORMAL.getCode()));
            if (verify && inviteRelationCount == 0) {
                String key = BizConstants.REGISTER_CHECK_FAIL_COUNT + phone;
                Integer cacheObject = redisCache.getCacheObject(key);
                if (cacheObject != null && cacheObject >= 3) {
                    throw new BusinessException(RspEnmu.INVITATION_CODE_INVALID_MORE_THREE);
                }
                redisCache.setCacheObject(key, (cacheObject == null ? 0 : cacheObject) + 1, 60 * 30, TimeUnit.SECONDS);
                throw new BusinessException(RspEnmu.INVITATION_CODE_INVALID);
            }

            //邀请有效即返回
            if (inviteRelationCount > 0) return inviteCodes[i];
        }
        return null;

    }

    public List<ProductInfo> getDefault() {
        List<ProductInfo> productInfoList = bProductService.getActiveDefaultProductList();
        return productInfoList;
    }

    public JSONObject getUserQuota(JSONObject dataJson) {

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("quota", 0);
        jsonObject.put("startQuota", 0);
        jsonObject.put("endQuota", 0);
        jsonObject.put("isInvalid", false);
        jsonObject.put("invalidDays", 0);
        jsonObject.put("canQuota", 0);

        if (null == dataJson.get("userId") || StringUtils.isBlank(dataJson.get("userId").toString())) {
            return jsonObject;
        }
        String userUUId = dataJson.get("userId").toString();

        CustomerInfo custQuery = new CustomerInfo();
        custQuery.setUserId(userUUId);
        List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(custQuery);
        if (customerInfoList.size() < 1) {
            throw new BusinessException(RspEnmu.SYSTEM_SYSDATA_EXCEPTION);
        }
        CustomerInfo custInfo = customerInfoList.get(0);
        String custNo = custInfo.getCustNo();

        CreditAccount creditAccount = new CreditAccount();
        creditAccount.setCustNo(custNo);
        creditAccount.setState(UserConstants.BUSINESS_NORMAL);
        List<CreditAccount> creditAccountList = creditAccountService.selectCreditAccountList(creditAccount);
        if (CollectionUtils.isEmpty(creditAccountList)) {
            return jsonObject;
        }

        creditAccount = creditAccountList.get(0);

        //授信额度
        BigDecimal creditQuota = creditAccount.getCreditLine();

        //冻结额度
        BigDecimal frozenQuota = creditAccount.getFrozenQuota() == null ? BigDecimal.ZERO : creditAccount.getFrozenQuota();
        //在贷额度
        BigDecimal loanQuota = creditAccount.getLoanQuota() == null ? BigDecimal.ZERO : creditAccount.getLoanQuota();
        //已借额度
        BigDecimal borrowedQuota = loanQuota.add(frozenQuota);

        // 可提现额度比例
        BigDecimal loanQuotaRatio = BigDecimal.ONE;

        CustBankCard custBankCard = new CustBankCard();
        custBankCard.setUserId(userUUId);
        custBankCard.setState(BizConstants.BIZ_STATUS_1);
        //查询卡片有效期
        List<CustBankCard> custBankCardList = custBankCardService.selectCustBankCardList(custBankCard);
        //判断是否为空
        List<CustBankCard> dayss = new ArrayList<>();
        if (custBankCardList != null) {
            for (int i = 0; i < custBankCardList.size(); i++) {
                //判断卡片是否有效
                CustBankCard bankCard = custBankCardList.get(i);
                log.debug("判断卡片是否有效");
                if (("1").equals(bankCard.getCardStatus())) {
                    jsonObject.put("isInvalid", true);
                    dayss.add(bankCard);
                }
            }
        }

//        if (dayss.size() == custBankCardList.size()) {
//            jsonObject.put("isInvalid", true);
//            if (dayss.size() != 0) {
//                jsonObject.put("invalidDays", Collections.max(dayss));
//            }
        //  }

//        Integer cardInvalidDays = Integer.valueOf(iSysConfigService.selectConfigByKey("card_invalid_days"));
//        try {
//            for (int i = 0; i < custBankCardList.size(); i++) {
//                //判断是否有卡在90天之后
//                CustBankCard custBankCard1 = custBankCardList.get(i);
//                int days = DateUtils.daysBetween(new Date(), DateUtils.parseDate(custBankCard1.getExpireDate() + "01", "yyyyMMdd"));
//                log.debug("判断是否有卡在90天之后判断是否有卡在90天之后：{}", days);
//                if (days < cardInvalidDays) {
//                    dayss.add(days);
//                }
//            }
//        } catch (Exception e) {
//            log.error("", e);
//        }
//
//        if (dayss.size() == custBankCardList.size()) {
//            jsonObject.put("isInvalid", true);
//            if (dayss.size() != 0) {
//                jsonObject.put("invalidDays", Collections.max(dayss));
//            }
//        }

        // >= 2.2.0
        if (VersionUtils.compareVersion(getAppVersion(), "2.2.0") >= 0) {
            if (CollectionUtils.isEmpty(custBankCardList) || dayss.size() == custBankCardList.size()) {
                loanQuotaRatio = BigDecimal.valueOf(Double.valueOf(dictDataService.selectDictLabel("loan_settings", "loan_quota_ratio")));
            }
        } else {
            // 获取绑卡可提现利率
            loanQuotaRatio = bankCardService.getLoanQuotaRatio(custInfo);
        }

        String startQuota = iSysConfigService.selectConfigByKey("startQuota");

        jsonObject.put("endQuota", creditQuota);
        jsonObject.put("startQuota", startQuota);
        //可提现
        BigDecimal bigDecimal = creditQuota.multiply(loanQuotaRatio).subtract(borrowedQuota).setScale(0, BigDecimal.ROUND_DOWN);
        //可用
        BigDecimal canQuota = creditQuota.subtract(borrowedQuota).setScale(0, BigDecimal.ROUND_DOWN);
        jsonObject.put("quota", bigDecimal.doubleValue() < 0 ? 0 : bigDecimal);
        jsonObject.put("canQuota", canQuota.doubleValue() < 0 ? 0 : canQuota);
        return jsonObject;
    }


    public JSONObject checkCanLoan(JSONObject dataJson) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("isOverdue", true);
        jsonObject.put("isColse", true);


        if (null == dataJson.get("userId") || StringUtils.isBlank(dataJson.get("userId").toString())) {
            return jsonObject;
        }

        String userId = dataJson.getString("userId");

        RealNameAuth realNameAuth = new RealNameAuth();
        realNameAuth.setUserId(userId);
        realNameAuth.setState(BizConstants.BIZ_STATUS_1);
        List<RealNameAuth> realNameAuths = realNameAuthService.selectRealNameAuthList(realNameAuth);

        if (realNameAuths.size() == 0) {
            log.error("未实名");
            return jsonObject;
        }

        CreditAccount creditAccount = new CreditAccount();
        creditAccount.setCustNo(realNameAuths.get(0).getCustNo());
        creditAccount.setState(UserConstants.BUSINESS_NORMAL);
        List<CreditAccount> creditAccountList = creditAccountService.selectCreditAccountList(creditAccount);
        if (CollectionUtils.isEmpty(creditAccountList)) {
            log.error("未CreditAccount");
            return jsonObject;
        }

        creditAccount = creditAccountList.get(0);

        //授信额度
        BigDecimal creditQuota = creditAccount.getCreditLine();

        //未结清合同总本金
        BigDecimal overdueAmountTotal = BigDecimal.ZERO;
        List<LoanIou> loanIouStatus0 = new ArrayList<>();

        LoanIou loanIou = new LoanIou();
        loanIou.setCustNo(realNameAuths.get(0).getCustNo());
        loanIou.setState(BizConstants.BIZ_STATUS_1);
        List<LoanIou> loanIous = loanIouService.selectLoanIouList(loanIou);
        jsonObject.put("isOverdue", false);
        for (int i = 0; i < loanIous.size(); i++) {
            LoanIou loanIou1 = loanIous.get(i);
            if (loanIou1.getIouStatus() == 2) {
                jsonObject.put("isOverdue", true);
            } else if (loanIou1.getIouStatus() == 0) {
                loanIouStatus0.add(loanIou1);
            }
            if (loanIou1.getIouStatus() != 1) {
                overdueAmountTotal = overdueAmountTotal.add(loanIou1.getLoanPrincipal().subtract(loanIou1.getRepaidPrincipal()));
            }
        }
        Date minDueDate = null;//最小还款日
        if (loanIouStatus0.size() > 0) {
            Collections.sort(loanIouStatus0, Comparator.comparing(o -> DateUtils.parseDate(o.getRepayDate())));
            minDueDate = DateUtils.parseDate(loanIouStatus0.get(0).getRepayDate());
        }

        log.debug("=====" + overdueAmountTotal);
        log.debug("=====" + creditQuota);
        log.debug("=====" + minDueDate);

        try {
            if (minDueDate == null || !DateUtils.isToday(minDueDate) || creditQuota.subtract(overdueAmountTotal).divide(creditQuota, 2, BigDecimal.ROUND_DOWN).doubleValue() < 0.5) {
                jsonObject.put("isColse", false);
            }
        } catch (Exception e) {
            log.error("", e);
            return jsonObject;
        }
        return jsonObject;
    }

    public JSONObject resetPassword(JSONObject dataJson) {

        JSONObject rsp = new JSONObject();

        String password = dataJson.get("password").toString();
        String oldPassword = dataJson.get("oldPassword").toString();
        String userId = dataJson.get("userId").toString();

        boolean tokenResult = this.gethasLoginResult(userId);
        //登录标记
        if (!tokenResult) {
            throw new BusinessException(RspEnmu.USER_LOGIN_OUT);
        }

        //查找用户
        AppUser userQuery = new AppUser();
        userQuery.setUserUuid(userId);
        List<AppUser> inviteCodeList = appUserService.selectAppUserList(userQuery);
        if (inviteCodeList.size() < 1) {
            throw new BusinessException(RspEnmu.USER_NOT_EXIST);
        }
        AppUser user = inviteCodeList.get(0);

        //状态检查
        if (!"0".equals(user.getState())) {
            throw new BusinessException(RspEnmu.USER_STATUS_ERR);
        }

        if (!bCryptPasswordEncoder.matches(oldPassword, user.getPassword())) {
            throw new BusinessException(RspEnmu.USER_PASSWORD_ERR);
        }

        //对密码进行加密
        user.setPassword(bCryptPasswordEncoder.encode(password));
        appUserService.updateAppUser(user);

        return rsp;
    }

    public String getSysConfigValueByKey(String key) {
        return iSysConfigService.selectConfigByKey(key);
    }

    public void repeatSubmit(String serialNo) {
        String requestURI = ServletUtils.getRequest().getRequestURI();
        String key = REPEAT_SUBMIT + ":" + requestURI + ":" + getUserId();
        Object sessionObj = redisCache.getCacheObject(key);
        if (sessionObj != null && serialNo.equals(sessionObj.toString())) {
            log.info("repeatSubmit 未失效，sessionObj:{},{}", sessionObj, serialNo);
            throw new BusinessException(RspEnmu.DUPLICATE_SUBMISSION);
        }
        redisCache.setCacheObject(key, serialNo, 10, TimeUnit.SECONDS);
    }

    public void repeatSubmit(String serialNo, String userId) {
        String requestURI = ServletUtils.getRequest().getRequestURI();
        String key = REPEAT_SUBMIT + ":" + requestURI + ":" + getUserId();
        Object sessionObj = redisCache.getCacheObject(key);
        if (sessionObj != null && serialNo.equals(sessionObj.toString())) {
            log.info("repeatSubmit未失效，sessionObj:{},{}", sessionObj, serialNo);
            throw new BusinessException(RspEnmu.SYSTEM_BUSY);
        }
        redisCache.setCacheObject(key, serialNo, 10, TimeUnit.SECONDS);
    }


    /**
     * appLogs日志文件上传
     */
    public void uploadAppLogs(MultipartFile[] files,Long type){
        // 获取文件原本的名字
        for (MultipartFile file : files) {
            String saveName = file.getOriginalFilename();
            String filePath = null;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
            String format = sdf.format(new Date());
            //String savePath = "/Users/mac/lcredit-pdl/appLogs";
            String savePath = AwsConfig.getLocalPath();
            File folder = new File(savePath);
            if (!folder.exists()) {
                folder.mkdirs();
            }
            try {
                file.transferTo(new File(folder, saveName));
                filePath = savePath + "/" + saveName;
                log.info("文件路径: "+ filePath);
                String key = AwsConfig.getAppLogsPath()+ format + saveName;
                //上传AWS
                URL url = AwsUtil.uploadObject(AwsConfig.getBucketName(), key, filePath);
                SysFiles sysFiles = new SysFiles();
                sysFiles.setAwsS3Url(String.valueOf(url));
                sysFiles.setType(type);
                sysFilesService.insertSysFiles(sysFiles);
                log.info("url: {} ", String.valueOf(url));
            } catch (IOException e) {
                log.error("上传失败", e);
            } finally {
                File filess = new File(filePath);
                if (filess.exists()) {
                    filess.delete();
                    log.info("删除成功");
                }
            }
        }

    }
}

